summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore103
-rw-r--r--.gitmodules6
-rw-r--r--Makefile.am172
-rw-r--r--README-1ST120
-rw-r--r--README.textile162
-rw-r--r--TODO1088
-rwxr-xr-xacprep1630
-rw-r--r--amount.cc2018
-rw-r--r--amount.h631
-rw-r--r--amounts.cc14
-rw-r--r--balance.cc529
-rw-r--r--balance.h961
-rw-r--r--binary.cc1338
-rw-r--r--binary.h26
-rw-r--r--config.cc132
-rw-r--r--config.h79
-rw-r--r--configure.in280
-rw-r--r--contrib/CSVReader.cs165
-rw-r--r--contrib/Makefile4
-rw-r--r--contrib/ParseCcStmt.cs184
-rw-r--r--contrib/README (renamed from scripts/README)0
-rwxr-xr-xcontrib/bal (renamed from scripts/bal)0
-rwxr-xr-xcontrib/bal-huquq (renamed from scripts/bal-huquq)0
-rwxr-xr-xcontrib/entry (renamed from scripts/entry)6
-rwxr-xr-xcontrib/getquote-uk.py23
-rwxr-xr-xcontrib/getquote.pl (renamed from scripts/getquote)5
-rwxr-xr-xcontrib/ledger-du (renamed from scripts/ledger-du)14
-rwxr-xr-xcontrib/repl.sh13
-rwxr-xr-xcontrib/report (renamed from scripts/report)0
-rwxr-xr-xcontrib/tc (renamed from scripts/tc)0
-rwxr-xr-xcontrib/ti (renamed from scripts/ti)0
-rwxr-xr-xcontrib/to (renamed from scripts/to)0
-rwxr-xr-xcontrib/trend (renamed from scripts/trend)0
-rw-r--r--contrib/vim/README100
-rw-r--r--contrib/vim/ftplugin/ledger.vim302
-rw-r--r--contrib/vim/syntax/ledger.vim49
-rw-r--r--csv.cc105
-rw-r--r--csv.h24
m---------data0
-rw-r--r--datetime.cc372
-rw-r--r--datetime.h307
-rw-r--r--debug.cc125
-rw-r--r--debug.h146
-rw-r--r--derive.cc202
-rw-r--r--derive.h14
-rw-r--r--dist/Portfile77
-rw-r--r--dist/pkg/ledger.pmdoc/01libgmp-contents.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/01libgmp.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/02libintl-contents.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/02libintl.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/03libosp-contents.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/03libosp.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/04libofx-contents.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/04libofx.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/05libpcre-contents.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/05libpcre.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/06ledger-contents.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/06ledger.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/07ledger-contents.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/07ledger.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/08ledger-contents.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/08ledger.xml1
-rw-r--r--dist/pkg/ledger.pmdoc/index.xml1
-rwxr-xr-xdist/pkg/post-install.sh8
-rw-r--r--doc/Doxyfile1485
-rw-r--r--doc/INSTALL234
-rw-r--r--doc/LICENSE (renamed from LICENSE)2
-rw-r--r--doc/LICENSE-sha113
-rw-r--r--doc/LICENSE-utfcpp23
-rw-r--r--doc/Ledger.scriv/100.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/101.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/102.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/103.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/104.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/105.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/106.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/107.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/108.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/109.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/110.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/111.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/112.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/113.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/114.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/115.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/116.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/117.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/118.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/119.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/12.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/120.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/121.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/122.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/123.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/124.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/125.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/126.rtfd/TXT.rtf39
-rw-r--r--doc/Ledger.scriv/128.rtfd/TXT.rtf11
-rw-r--r--doc/Ledger.scriv/129.rtfd/TXT.rtf22
-rw-r--r--doc/Ledger.scriv/13.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/130.rtfd/TXT.rtf13
-rw-r--r--doc/Ledger.scriv/131.rtfd/TXT.rtf17
-rw-r--r--doc/Ledger.scriv/132.rtfd/TXT.rtf10
-rw-r--r--doc/Ledger.scriv/133.rtfd/TXT.rtf13
-rw-r--r--doc/Ledger.scriv/134.rtfd/TXT.rtf8
-rw-r--r--doc/Ledger.scriv/135.rtfd/TXT.rtf13
-rw-r--r--doc/Ledger.scriv/136.rtfd/TXT.rtf57
-rw-r--r--doc/Ledger.scriv/137.rtfd/TXT.rtf19
-rw-r--r--doc/Ledger.scriv/138.rtfd/TXT.rtf53
-rw-r--r--doc/Ledger.scriv/139.rtfd/TXT.rtf102
-rw-r--r--doc/Ledger.scriv/14.rtfd/TXT.rtf16
-rw-r--r--doc/Ledger.scriv/140.rtfd/TXT.rtf127
-rw-r--r--doc/Ledger.scriv/141.rtfd/TXT.rtf54
-rw-r--r--doc/Ledger.scriv/142.rtfd/TXT.rtf18
-rw-r--r--doc/Ledger.scriv/143.rtfd/TXT.rtf88
-rw-r--r--doc/Ledger.scriv/144.rtfd/TXT.rtf149
-rw-r--r--doc/Ledger.scriv/145.rtfd/TXT.rtf52
-rw-r--r--doc/Ledger.scriv/146.rtfd/TXT.rtf28
-rw-r--r--doc/Ledger.scriv/147.rtfd/TXT.rtf42
-rw-r--r--doc/Ledger.scriv/148.rtfd/TXT.rtf27
-rw-r--r--doc/Ledger.scriv/149.rtfd/TXT.rtf26
-rw-r--r--doc/Ledger.scriv/15.rtfd/TXT.rtf14
-rw-r--r--doc/Ledger.scriv/150.rtfd/TXT.rtf13
-rw-r--r--doc/Ledger.scriv/151.rtfd/TXT.rtf48
-rw-r--r--doc/Ledger.scriv/152.rtfd/TXT.rtf131
-rw-r--r--doc/Ledger.scriv/153.rtfd/TXT.rtf45
-rw-r--r--doc/Ledger.scriv/155.rtfd/TXT.rtf88
-rw-r--r--doc/Ledger.scriv/156.rtfd/TXT.rtf57
-rw-r--r--doc/Ledger.scriv/157.rtfd/TXT.rtf51
-rw-r--r--doc/Ledger.scriv/158.rtfd/TXT.rtf70
-rw-r--r--doc/Ledger.scriv/159.rtfd/TXT.rtf37
-rw-r--r--doc/Ledger.scriv/16.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/160.rtfd/TXT.rtf12
-rw-r--r--doc/Ledger.scriv/161.rtfd/TXT.rtf93
-rw-r--r--doc/Ledger.scriv/162.rtfd/TXT.rtf46
-rw-r--r--doc/Ledger.scriv/164.rtfd/TXT.rtf35
-rw-r--r--doc/Ledger.scriv/165.rtfd/TXT.rtf102
-rw-r--r--doc/Ledger.scriv/166.rtfd/TXT.rtf42
-rw-r--r--doc/Ledger.scriv/168.rtfd/TXT.rtf11
-rw-r--r--doc/Ledger.scriv/169.rtfd/TXT.rtf108
-rw-r--r--doc/Ledger.scriv/17.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/170.rtfd/TXT.rtf35
-rw-r--r--doc/Ledger.scriv/171.rtfd/TXT.rtf59
-rw-r--r--doc/Ledger.scriv/172.rtfd/TXT.rtf47
-rw-r--r--doc/Ledger.scriv/173.rtfd/TXT.rtf19
-rw-r--r--doc/Ledger.scriv/174.rtfd/TXT.rtf19
-rw-r--r--doc/Ledger.scriv/175.rtfd/TXT.rtf74
-rw-r--r--doc/Ledger.scriv/176.rtfd/TXT.rtf44
-rw-r--r--doc/Ledger.scriv/177.rtfd/TXT.rtf36
-rw-r--r--doc/Ledger.scriv/178.rtfd/TXT.rtf7
-rw-r--r--doc/Ledger.scriv/18.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/180.rtfd/TXT.rtf51
-rw-r--r--doc/Ledger.scriv/181.rtfd/TXT.rtf67
-rw-r--r--doc/Ledger.scriv/182.rtfd/TXT.rtf151
-rw-r--r--doc/Ledger.scriv/183.rtfd/TXT.rtf15
-rw-r--r--doc/Ledger.scriv/184.rtfd/TXT.rtf44
-rw-r--r--doc/Ledger.scriv/185.rtfd/TXT.rtf30
-rw-r--r--doc/Ledger.scriv/186.rtfd/TXT.rtf23
-rw-r--r--doc/Ledger.scriv/188.rtfd/TXT.rtf65
-rw-r--r--doc/Ledger.scriv/189.rtfd/TXT.rtf24
-rw-r--r--doc/Ledger.scriv/19.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/190.rtfd/TXT.rtf93
-rw-r--r--doc/Ledger.scriv/191.rtfd/TXT.rtf23
-rw-r--r--doc/Ledger.scriv/192.rtfd/TXT.rtf55
-rw-r--r--doc/Ledger.scriv/193.rtfd/TXT.rtf39
-rw-r--r--doc/Ledger.scriv/194.rtfd/TXT.rtf40
-rw-r--r--doc/Ledger.scriv/195.rtfd/TXT.rtf32
-rw-r--r--doc/Ledger.scriv/196.rtfd/TXT.rtf137
-rw-r--r--doc/Ledger.scriv/197.rtfd/TXT.rtf61
-rw-r--r--doc/Ledger.scriv/198.rtfd/TXT.rtf42
-rw-r--r--doc/Ledger.scriv/199.rtfd/TXT.rtf79
-rw-r--r--doc/Ledger.scriv/20.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/200.rtfd/TXT.rtf104
-rw-r--r--doc/Ledger.scriv/201.rtfd/TXT.rtf18
-rw-r--r--doc/Ledger.scriv/202.rtfd/TXT.rtf92
-rw-r--r--doc/Ledger.scriv/203.rtfd/TXT.rtf152
-rw-r--r--doc/Ledger.scriv/204.rtfd/TXT.rtf41
-rw-r--r--doc/Ledger.scriv/205.rtfd/TXT.rtf39
-rw-r--r--doc/Ledger.scriv/207.rtfd/TXT.rtf18
-rw-r--r--doc/Ledger.scriv/21.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/211.rtfd/TXT.rtf29
-rw-r--r--doc/Ledger.scriv/213.rtfd/TXT.rtf22
-rw-r--r--doc/Ledger.scriv/214.rtfd/TXT.rtf10
-rw-r--r--doc/Ledger.scriv/218.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/219.rtfd/TXT.rtf8
-rw-r--r--doc/Ledger.scriv/22.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/220.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/221.rtfd/TXT.rtf12
-rw-r--r--doc/Ledger.scriv/222.rtfd/TXT.rtf20
-rw-r--r--doc/Ledger.scriv/222_synopsis.txt1
-rw-r--r--doc/Ledger.scriv/23.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/24.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/25.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/26.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/28.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/29.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/30.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/31.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/32.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/33.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/4.rtfd/TXT.rtf11
-rw-r--r--doc/Ledger.scriv/44.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/5.rtfd/TXT.rtf63
-rw-r--r--doc/Ledger.scriv/54.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/55.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/56.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/57.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/58.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/59.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/6.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/60.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/61.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/62.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/63.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/64.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/65.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/66.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/67.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/69.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/7.rtfd/TXT.rtf125
-rw-r--r--doc/Ledger.scriv/70.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/71.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/72.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/73.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/74.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/75.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/76.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/77.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/78.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/79.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/8.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/80.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/81.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/82.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/83.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/84.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/85.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/86.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/87.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/88.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/89.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/9.rtfd/TXT.rtf55
-rw-r--r--doc/Ledger.scriv/90.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/91.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/92.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/93.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/94.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/95.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/96.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/97.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/98.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/99.rtfd/TXT.rtf6
-rw-r--r--doc/Ledger.scriv/BinderStrings.xml5741
-rw-r--r--doc/Ledger.scriv/ExportSettings.xml113
-rw-r--r--doc/Ledger.scriv/ProjectNotes.rtfd/TXT.rtf4
-rw-r--r--doc/Ledger.scriv/QuickLook/Preview.html563
-rw-r--r--doc/Ledger.scriv/QuickLook/Thumbnail.jpgbin0 -> 33306 bytes
-rw-r--r--doc/Ledger.scriv/binder.scrivproj34782
-rw-r--r--doc/Ledger.scriv/info.plist8
-rw-r--r--doc/Ledger.scriv/snapshots/100.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/101.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/102.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/103.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/104.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/105.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/106.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/107.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/108.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/109.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/110.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/111.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/112.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/113.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/114.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/115.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/116.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/117.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/118.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/119.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/12.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/120.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/121.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/122.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/123.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/124.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/125.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/126.snapshots466
-rw-r--r--doc/Ledger.scriv/snapshots/128.snapshots438
-rw-r--r--doc/Ledger.scriv/snapshots/129.snapshots449
-rw-r--r--doc/Ledger.scriv/snapshots/13.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/130.snapshots440
-rw-r--r--doc/Ledger.scriv/snapshots/131.snapshots444
-rw-r--r--doc/Ledger.scriv/snapshots/132.snapshots437
-rw-r--r--doc/Ledger.scriv/snapshots/133.snapshots440
-rw-r--r--doc/Ledger.scriv/snapshots/134.snapshots435
-rw-r--r--doc/Ledger.scriv/snapshots/135.snapshots440
-rw-r--r--doc/Ledger.scriv/snapshots/136.snapshots484
-rw-r--r--doc/Ledger.scriv/snapshots/137.snapshots446
-rw-r--r--doc/Ledger.scriv/snapshots/138.snapshots480
-rw-r--r--doc/Ledger.scriv/snapshots/139.snapshots529
-rw-r--r--doc/Ledger.scriv/snapshots/14.snapshots443
-rw-r--r--doc/Ledger.scriv/snapshots/140.snapshots554
-rw-r--r--doc/Ledger.scriv/snapshots/141.snapshots481
-rw-r--r--doc/Ledger.scriv/snapshots/142.snapshots445
-rw-r--r--doc/Ledger.scriv/snapshots/143.snapshots515
-rw-r--r--doc/Ledger.scriv/snapshots/144.snapshots576
-rw-r--r--doc/Ledger.scriv/snapshots/145.snapshots479
-rw-r--r--doc/Ledger.scriv/snapshots/146.snapshots455
-rw-r--r--doc/Ledger.scriv/snapshots/147.snapshots469
-rw-r--r--doc/Ledger.scriv/snapshots/148.snapshots454
-rw-r--r--doc/Ledger.scriv/snapshots/149.snapshots453
-rw-r--r--doc/Ledger.scriv/snapshots/15.snapshots441
-rw-r--r--doc/Ledger.scriv/snapshots/150.snapshots440
-rw-r--r--doc/Ledger.scriv/snapshots/151.snapshots475
-rw-r--r--doc/Ledger.scriv/snapshots/152.snapshots558
-rw-r--r--doc/Ledger.scriv/snapshots/153.snapshots472
-rw-r--r--doc/Ledger.scriv/snapshots/155.snapshots515
-rw-r--r--doc/Ledger.scriv/snapshots/156.snapshots484
-rw-r--r--doc/Ledger.scriv/snapshots/157.snapshots478
-rw-r--r--doc/Ledger.scriv/snapshots/158.snapshots497
-rw-r--r--doc/Ledger.scriv/snapshots/159.snapshots464
-rw-r--r--doc/Ledger.scriv/snapshots/16.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/160.snapshots439
-rw-r--r--doc/Ledger.scriv/snapshots/161.snapshots520
-rw-r--r--doc/Ledger.scriv/snapshots/162.snapshots473
-rw-r--r--doc/Ledger.scriv/snapshots/164.snapshots462
-rw-r--r--doc/Ledger.scriv/snapshots/165.snapshots529
-rw-r--r--doc/Ledger.scriv/snapshots/166.snapshots469
-rw-r--r--doc/Ledger.scriv/snapshots/168.snapshots438
-rw-r--r--doc/Ledger.scriv/snapshots/169.snapshots535
-rw-r--r--doc/Ledger.scriv/snapshots/17.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/170.snapshots462
-rw-r--r--doc/Ledger.scriv/snapshots/171.snapshots486
-rw-r--r--doc/Ledger.scriv/snapshots/172.snapshots474
-rw-r--r--doc/Ledger.scriv/snapshots/173.snapshots446
-rw-r--r--doc/Ledger.scriv/snapshots/174.snapshots446
-rw-r--r--doc/Ledger.scriv/snapshots/175.snapshots501
-rw-r--r--doc/Ledger.scriv/snapshots/176.snapshots471
-rw-r--r--doc/Ledger.scriv/snapshots/177.snapshots463
-rw-r--r--doc/Ledger.scriv/snapshots/178.snapshots434
-rw-r--r--doc/Ledger.scriv/snapshots/18.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/180.snapshots478
-rw-r--r--doc/Ledger.scriv/snapshots/181.snapshots494
-rw-r--r--doc/Ledger.scriv/snapshots/182.snapshots578
-rw-r--r--doc/Ledger.scriv/snapshots/183.snapshots442
-rw-r--r--doc/Ledger.scriv/snapshots/184.snapshots471
-rw-r--r--doc/Ledger.scriv/snapshots/185.snapshots457
-rw-r--r--doc/Ledger.scriv/snapshots/186.snapshots450
-rw-r--r--doc/Ledger.scriv/snapshots/188.snapshots492
-rw-r--r--doc/Ledger.scriv/snapshots/189.snapshots451
-rw-r--r--doc/Ledger.scriv/snapshots/19.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/190.snapshots520
-rw-r--r--doc/Ledger.scriv/snapshots/191.snapshots450
-rw-r--r--doc/Ledger.scriv/snapshots/192.snapshots482
-rw-r--r--doc/Ledger.scriv/snapshots/193.snapshots466
-rw-r--r--doc/Ledger.scriv/snapshots/194.snapshots467
-rw-r--r--doc/Ledger.scriv/snapshots/195.snapshots459
-rw-r--r--doc/Ledger.scriv/snapshots/196.snapshots564
-rw-r--r--doc/Ledger.scriv/snapshots/197.snapshots488
-rw-r--r--doc/Ledger.scriv/snapshots/198.snapshots469
-rw-r--r--doc/Ledger.scriv/snapshots/199.snapshots506
-rw-r--r--doc/Ledger.scriv/snapshots/20.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/200.snapshots531
-rw-r--r--doc/Ledger.scriv/snapshots/201.snapshots445
-rw-r--r--doc/Ledger.scriv/snapshots/202.snapshots519
-rw-r--r--doc/Ledger.scriv/snapshots/203.snapshots579
-rw-r--r--doc/Ledger.scriv/snapshots/204.snapshots468
-rw-r--r--doc/Ledger.scriv/snapshots/205.snapshots466
-rw-r--r--doc/Ledger.scriv/snapshots/207.snapshots445
-rw-r--r--doc/Ledger.scriv/snapshots/21.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/211.snapshots456
-rw-r--r--doc/Ledger.scriv/snapshots/213.snapshots449
-rw-r--r--doc/Ledger.scriv/snapshots/214.snapshots437
-rw-r--r--doc/Ledger.scriv/snapshots/218.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/22.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/23.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/24.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/25.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/26.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/28.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/29.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/30.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/31.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/32.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/33.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/4.snapshots438
-rw-r--r--doc/Ledger.scriv/snapshots/44.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/5.snapshots490
-rw-r--r--doc/Ledger.scriv/snapshots/54.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/55.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/56.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/57.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/58.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/59.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/6.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/60.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/61.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/62.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/63.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/64.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/65.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/66.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/67.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/69.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/7.snapshots552
-rw-r--r--doc/Ledger.scriv/snapshots/70.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/71.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/72.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/73.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/74.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/75.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/76.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/77.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/78.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/79.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/8.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/80.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/81.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/82.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/83.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/84.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/85.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/86.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/87.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/88.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/89.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/9.snapshots482
-rw-r--r--doc/Ledger.scriv/snapshots/90.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/91.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/92.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/93.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/94.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/95.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/96.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/97.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/98.snapshots433
-rw-r--r--doc/Ledger.scriv/snapshots/99.snapshots433
-rw-r--r--doc/Ledger.scriv/ui.xml3529
-rw-r--r--doc/NEWS (renamed from NEWS)150
-rw-r--r--doc/README (renamed from README)53
-rw-r--r--doc/grammar.y221
-rw-r--r--doc/ledger.1583
-rw-r--r--doc/ledger.texi (renamed from ledger.texi)3461
-rw-r--r--doc/sample.dat54
-rw-r--r--emacs.cc80
-rw-r--r--emacs.h30
-rw-r--r--error.h125
-rw-r--r--fdstream.hpp184
-rw-r--r--format.cc985
-rw-r--r--format.h218
-rw-r--r--gnucash.cc413
-rw-r--r--gnucash.h22
-rw-r--r--journal.cc655
-rw-r--r--journal.h466
-rw-r--r--ledger.h51
-rw-r--r--ledger.vim46
-rw-r--r--lib/Makefile59
-rw-r--r--lib/gettext.h271
-rw-r--r--lib/sha1.cpp589
-rw-r--r--lib/sha1.h89
m---------lib/utfcpp0
-rw-r--r--lisp/ledger.el (renamed from ledger.el)184
-rw-r--r--lisp/timeclock.el (renamed from timeclock.el)0
-rw-r--r--main.cc496
-rw-r--r--mask.cc53
-rw-r--r--mask.h29
-rw-r--r--ofx.cc226
-rw-r--r--ofx.h22
-rw-r--r--option.cc1065
-rw-r--r--option.h53
-rw-r--r--parser.cc196
-rw-r--r--parser.h62
-rw-r--r--python/__init__.py0
-rwxr-xr-xpython/demo.py293
-rw-r--r--python/res/asc.gifbin0 -> 54 bytes
-rw-r--r--python/res/bg.gifbin0 -> 64 bytes
-rw-r--r--python/res/desc.gifbin0 -> 54 bytes
-rw-r--r--python/res/icons/first.pngbin0 -> 720 bytes
-rw-r--r--python/res/icons/last.pngbin0 -> 737 bytes
-rw-r--r--python/res/icons/next.pngbin0 -> 736 bytes
-rw-r--r--python/res/icons/prev.pngbin0 -> 745 bytes
-rw-r--r--python/res/jquery-latest.js32
-rw-r--r--python/res/jquery.dimensions.min.js12
-rw-r--r--python/res/jquery.metadata.js122
-rw-r--r--python/res/jquery.tablesorter.min.js2
-rw-r--r--python/res/jquery.tablesorter.pager.css25
-rw-r--r--python/res/jquery.tablesorter.pager.js184
-rw-r--r--python/res/style.css39
-rw-r--r--python/server.py196
-rw-r--r--qif.cc250
-rw-r--r--qif.h22
-rw-r--r--quotes.cc82
-rw-r--r--quotes.h30
-rw-r--r--reconcile.cc88
-rw-r--r--reconcile.h33
-rw-r--r--report.cc413
-rw-r--r--report.h79
-rw-r--r--sample.dat26
-rwxr-xr-xsetup.py19
-rw-r--r--src/account.cc551
-rw-r--r--src/account.h273
-rw-r--r--src/accum.cc76
-rw-r--r--src/accum.h86
-rw-r--r--src/amount.cc1278
-rw-r--r--src/amount.h761
-rw-r--r--src/annotate.cc205
-rw-r--r--src/annotate.h265
-rw-r--r--src/archive.cc295
-rw-r--r--src/archive.h92
-rw-r--r--src/balance.cc310
-rw-r--r--src/balance.h602
-rw-r--r--src/chain.cc241
-rw-r--r--src/chain.h91
-rw-r--r--src/commodity.cc705
-rw-r--r--src/commodity.h431
-rw-r--r--src/compare.cc114
-rw-r--r--src/compare.h98
-rw-r--r--src/draft.cc527
-rw-r--r--src/draft.h113
-rw-r--r--src/emacs.cc108
-rw-r--r--src/emacs.h79
-rw-r--r--src/error.cc118
-rw-r--r--src/error.h104
-rw-r--r--src/expr.cc143
-rw-r--r--src/expr.h147
-rw-r--r--src/exprbase.h253
-rw-r--r--src/filters.cc1055
-rw-r--r--src/filters.h721
-rw-r--r--src/flags.h209
-rw-r--r--src/format.cc488
-rw-r--r--src/format.h161
-rw-r--r--src/generate.cc385
-rw-r--r--src/generate.h129
-rw-r--r--src/global.cc480
-rw-r--r--src/global.h163
-rw-r--r--src/interactive.cc194
-rw-r--r--src/interactive.h151
-rw-r--r--src/item.cc467
-rw-r--r--src/item.h215
-rw-r--r--src/iterators.cc258
-rw-r--r--src/iterators.h230
-rw-r--r--src/journal.cc251
-rw-r--r--src/journal.h197
-rw-r--r--src/main.cc217
-rw-r--r--src/mask.cc55
-rw-r--r--src/mask.h157
-rw-r--r--src/op.cc732
-rw-r--r--src/op.h343
-rw-r--r--src/option.cc249
-rw-r--r--src/option.h294
-rw-r--r--src/output.cc254
-rw-r--r--src/output.h110
-rw-r--r--src/parser.cc517
-rw-r--r--src/parser.h107
-rw-r--r--src/pool.cc364
-rw-r--r--src/pool.h156
-rw-r--r--src/post.cc576
-rw-r--r--src/post.h224
-rw-r--r--src/precmd.cc211
-rw-r--r--src/precmd.h59
-rw-r--r--src/predicate.cc46
-rw-r--r--src/predicate.h106
-rw-r--r--src/pstream.h109
-rw-r--r--src/py_account.cc235
-rw-r--r--src/py_amount.cc314
-rw-r--r--src/py_balance.cc238
-rw-r--r--src/py_commodity.cc451
-rw-r--r--src/py_expr.cc68
-rw-r--r--src/py_format.cc64
-rw-r--r--src/py_item.cc166
-rw-r--r--src/py_journal.cc321
-rw-r--r--src/py_post.cc184
-rw-r--r--src/py_times.cc253
-rw-r--r--src/py_utils.cc254
-rw-r--r--src/py_value.cc380
-rw-r--r--src/py_xact.cc153
-rw-r--r--src/pyfstream.h202
-rw-r--r--src/pyinterp.cc505
-rw-r--r--src/pyinterp.h124
-rw-r--r--src/pyledger.cc52
-rw-r--r--src/pyutils.h189
-rw-r--r--src/query.cc455
-rw-r--r--src/query.h305
-rw-r--r--src/quotes.cc109
-rw-r--r--src/quotes.h53
-rw-r--r--src/report.cc1307
-rw-r--r--src/report.h958
-rw-r--r--src/scope.cc74
-rw-r--r--src/scope.h348
-rw-r--r--src/session.cc248
-rw-r--r--src/session.h151
-rw-r--r--src/stats.cc121
-rw-r--r--src/stats.h55
-rw-r--r--src/stream.cc139
-rw-r--r--src/stream.h142
-rw-r--r--src/system.hh.in256
-rw-r--r--src/temps.cc137
-rw-r--r--src/temps.h76
-rw-r--r--src/textual.cc1396
-rw-r--r--src/timelog.cc158
-rw-r--r--src/timelog.h103
-rw-r--r--src/times.cc1587
-rw-r--r--src/times.h632
-rw-r--r--src/token.cc485
-rw-r--r--src/token.h135
-rw-r--r--src/unistring.h128
-rw-r--r--src/utils.cc821
-rw-r--r--src/utils.h713
-rw-r--r--src/value.cc1864
-rw-r--r--src/value.h998
-rw-r--r--src/xact.cc781
-rw-r--r--src/xact.h232
-rw-r--r--src/xml.cc124
-rw-r--r--src/xml.h90
-rw-r--r--startup.cc56
-rwxr-xr-xtest.py22
-rwxr-xr-xtest/ConfirmTests.py92
-rw-r--r--test/DataTests.cc3
-rw-r--r--test/ExprTests.cc3
-rwxr-xr-xtest/GenerateTests.py117
-rwxr-xr-xtest/LedgerHarness.py120
-rw-r--r--test/MathTests.cc3
-rwxr-xr-xtest/PyUnitTests.py6
-rwxr-xr-xtest/RegressTests.py159
-rw-r--r--test/ReportTests.cc3
-rw-r--r--test/UnitTests.cc116
-rw-r--r--test/UnitTests.h20
-rw-r--r--test/UtilTests.cc3
-rw-r--r--test/baseline/feat-balance-assignments.test37
-rw-r--r--test/baseline/feat-fixated-prices.test24
-rw-r--r--test/baseline/opt-abbrev-len.test11
-rw-r--r--test/baseline/opt-account-width.test11
-rw-r--r--test/baseline/opt-account.test11
-rw-r--r--test/baseline/opt-actual.test15
-rw-r--r--test/baseline/opt-add-budget.test368
-rw-r--r--test/baseline/opt-amount-data.test10
-rw-r--r--test/baseline/opt-amount-width.test11
-rw-r--r--test/baseline/opt-amount.test10
-rw-r--r--test/baseline/opt-anon.test11
-rw-r--r--test/baseline/opt-average.test244
-rw-r--r--test/baseline/opt-balance-format.test10
-rw-r--r--test/baseline/opt-base.test29
-rw-r--r--test/baseline/opt-basis.test12
-rw-r--r--test/baseline/opt-begin.test240
-rw-r--r--test/baseline/opt-budget.test321
-rw-r--r--test/baseline/opt-by-payee.test220
-rw-r--r--test/baseline/opt-cleared.test206
-rw-r--r--test/baseline/opt-code-as-account.test34
-rw-r--r--test/baseline/opt-code-as-payee.test34
-rw-r--r--test/baseline/opt-collapse-if-zero.test15
-rw-r--r--test/baseline/opt-collapse.test13
-rw-r--r--test/baseline/opt-collapse_reg.test46
-rw-r--r--test/baseline/opt-color.test13
-rw-r--r--test/baseline/opt-columns.test11
-rw-r--r--test/baseline/opt-commodity-as-account.test11
-rw-r--r--test/baseline/opt-commodity-as-payee.test11
-rw-r--r--test/baseline/opt-cost.test12
-rw-r--r--test/baseline/opt-csv-format.test10
-rw-r--r--test/baseline/opt-current.test17
-rw-r--r--test/baseline/opt-daily.test56
-rw-r--r--test/baseline/opt-date-format.test11
-rw-r--r--test/baseline/opt-date-width.test11
-rw-r--r--test/baseline/opt-depth.test93
-rw-r--r--test/baseline/opt-depth_flat.test68
-rw-r--r--test/baseline/opt-deviation.test244
-rw-r--r--test/baseline/opt-display-amount.test65
-rw-r--r--test/baseline/opt-display-total.test65
-rw-r--r--test/baseline/opt-display.test59
-rw-r--r--test/baseline/opt-dow.test55
-rw-r--r--test/baseline/opt-effective.test22
-rw-r--r--test/baseline/opt-empty.test36
-rw-r--r--test/baseline/opt-empty_bal.test41
-rw-r--r--test/baseline/opt-empty_bal_flat.test35
-rw-r--r--test/baseline/opt-empty_collapse.test28
-rw-r--r--test/baseline/opt-end.test248
-rw-r--r--test/baseline/opt-equity.test11
-rw-r--r--test/baseline/opt-exact.test225
-rw-r--r--test/baseline/opt-exchange.test81
-rw-r--r--test/baseline/opt-flat.test34
-rw-r--r--test/baseline/opt-forecast-while.test285
-rw-r--r--test/baseline/opt-format.test10
-rw-r--r--test/baseline/opt-gain.test66
-rw-r--r--test/baseline/opt-head.test206
-rw-r--r--test/baseline/opt-input-date-format.test11
-rw-r--r--test/baseline/opt-invert.test11
-rw-r--r--test/baseline/opt-limit.test212
-rw-r--r--test/baseline/opt-lot-dates.test4497
-rw-r--r--test/baseline/opt-lot-prices.test2891
-rw-r--r--test/baseline/opt-lot-tags.test12
-rw-r--r--test/baseline/opt-lots-actual.test27
-rw-r--r--test/baseline/opt-lots.test5373
-rw-r--r--test/baseline/opt-lots_basis.test890
-rw-r--r--test/baseline/opt-lots_basis_base.test891
-rw-r--r--test/baseline/opt-market.test66
-rw-r--r--test/baseline/opt-master-account.test15
-rw-r--r--test/baseline/opt-monthly.test220
-rw-r--r--test/baseline/opt-no-total.test10
-rw-r--r--test/baseline/opt-only.test236
-rw-r--r--test/baseline/opt-output.test11
-rw-r--r--test/baseline/opt-pager.test11
-rw-r--r--test/baseline/opt-payee-as-account.test34
-rw-r--r--test/baseline/opt-payee-width.test11
-rw-r--r--test/baseline/opt-payee.test11
-rw-r--r--test/baseline/opt-pending.test200
-rw-r--r--test/baseline/opt-percent.test94
-rw-r--r--test/baseline/opt-period.test290
-rw-r--r--test/baseline/opt-plot-amount-format.test10
-rw-r--r--test/baseline/opt-plot-total-format.test10
-rw-r--r--test/baseline/opt-price.test47
-rw-r--r--test/baseline/opt-pricedb-format.test21
-rw-r--r--test/baseline/opt-prices-format.test21
-rw-r--r--test/baseline/opt-print-format.test10
-rw-r--r--test/baseline/opt-quantity.test11
-rw-r--r--test/baseline/opt-quarterly.test204
-rw-r--r--test/baseline/opt-raw.test11
-rw-r--r--test/baseline/opt-real.test11
-rw-r--r--test/baseline/opt-register-format.test10
-rw-r--r--test/baseline/opt-related-all.test14
-rw-r--r--test/baseline/opt-related.test13
-rw-r--r--test/baseline/opt-revalued-only.test59
-rw-r--r--test/baseline/opt-revalued.test66
-rw-r--r--test/baseline/opt-seed.test.save432
-rw-r--r--test/baseline/opt-sort-all.test122
-rw-r--r--test/baseline/opt-sort-xacts.test176
-rw-r--r--test/baseline/opt-sort.test246
-rw-r--r--test/baseline/opt-start-of-week.test224
-rw-r--r--test/baseline/opt-strict.test23
-rw-r--r--test/baseline/opt-subtotal.test93
-rw-r--r--test/baseline/opt-tail.test206
-rw-r--r--test/baseline/opt-total-data.test10
-rw-r--r--test/baseline/opt-total-width.test11
-rw-r--r--test/baseline/opt-total.test10
-rw-r--r--test/baseline/opt-truncate.test144
-rw-r--r--test/baseline/opt-unbudgeted.test296
-rw-r--r--test/baseline/opt-uncleared.test286
-rw-r--r--test/baseline/opt-unrealized-gains.test20
-rw-r--r--test/baseline/opt-unrealized-losses.test20
-rw-r--r--test/baseline/opt-unrealized.test48
-rw-r--r--test/baseline/opt-unround.test94
-rw-r--r--test/baseline/opt-weekly.test225
-rw-r--r--test/baseline/opt-weekly_empty.test301
-rw-r--r--test/baseline/opt-wide.test11
-rw-r--r--test/baseline/opt-yearly.test198
-rw-r--r--test/baseline/test-sample.dat91
-rwxr-xr-xtest/convert.py191
-rwxr-xr-xtest/fullcheck.sh18
-rw-r--r--test/input/drewr.dat63
-rw-r--r--test/input/sample.dat54
-rw-r--r--test/input/standard.dat5619
-rw-r--r--test/input/transfer.dat220
-rw-r--r--test/input/wow.dat550
-rw-r--r--test/manual/transaction-codes-1.test22
-rw-r--r--test/manual/transaction-codes-2.test24
-rw-r--r--test/manual/transaction-notes-1.test24
-rw-r--r--test/manual/transaction-notes-2.test23
-rw-r--r--test/manual/transaction-notes-3.test23
-rw-r--r--test/manual/transaction-notes-4.test27
-rw-r--r--test/manual/transaction-status-1.test19
-rw-r--r--test/manual/transaction-status-2.test17
-rw-r--r--test/manual/transaction-status-3.test18
-rw-r--r--test/manual/transaction-status-4.test17
-rwxr-xr-xtest/prove.sh11
-rw-r--r--test/regress/04C5E1CA.test18
-rw-r--r--test/regress/0CA014F9.test13
-rw-r--r--test/regress/13965214.test30
-rw-r--r--test/regress/1CF1EEC2.test27
-rw-r--r--test/regress/25A099C9.test19
-rw-r--r--test/regress/2E3496BD.test20
-rw-r--r--test/regress/373540CC.test9
-rw-r--r--test/regress/3AB70168.test13
-rw-r--r--test/regress/461980A1.test13
-rw-r--r--test/regress/55831A79.test26
-rw-r--r--test/regress/5A03CFC3.test72
-rw-r--r--test/regress/5F1BAF17.test130
-rw-r--r--test/regress/5FBF2ED8.test20
-rw-r--r--test/regress/647D5DB9.test17
-rw-r--r--test/regress/6DAB9FE3.test10
-rw-r--r--test/regress/727B2DF8.test81
-rw-r--r--test/regress/793F6BF0.test52
-rw-r--r--test/regress/7F3650FD.test95
-rw-r--r--test/regress/8254755E.test20
-rw-r--r--test/regress/86D2BDC4.test12
-rw-r--r--test/regress/B68FFB0D.test15
-rw-r--r--test/regress/BBFA1759.test20
-rw-r--r--test/regress/C523E23F.test21
-rw-r--r--test/regress/D060256A.test16
-rw-r--r--test/regress/D943AE0F.test15
-rw-r--r--test/regress/E4C9A8EA.test24
-rw-r--r--test/regress/E627C594.test18
-rw-r--r--test/regress/E9F130C5.test30
-rw-r--r--test/regress/F559EC12.test43
-rwxr-xr-xtest/runtests.py180
-rw-r--r--test/unit/t_amount.cc1329
-rw-r--r--test/unit/t_amount.h105
-rw-r--r--test/unit/t_balance.cc29
-rw-r--r--test/unit/t_balance.h28
-rw-r--r--test/unit/t_commodity.cc106
-rw-r--r--test/unit/t_commodity.h28
-rw-r--r--test/unit/t_expr.cc332
-rw-r--r--test/unit/t_expr.h60
-rw-r--r--test/unit/t_times.cc166
-rw-r--r--test/unit/t_times.h28
-rw-r--r--test/unit/t_utils.cc6
-rw-r--r--test/unit/t_utils.h28
-rw-r--r--tests/amounts.h169
-rw-r--r--tests/baseline/10011
-rw-r--r--tests/baseline/10024
-rw-r--r--tests/baseline/10034
-rw-r--r--tests/baseline/10044
-rw-r--r--tests/baseline/10054
-rw-r--r--tests/baseline/10064
-rw-r--r--tests/baseline/10074
-rw-r--r--tests/baseline/10084
-rw-r--r--tests/baseline/10094
-rw-r--r--tests/baseline/10104
-rw-r--r--tests/baseline/10114
-rw-r--r--tests/baseline/10124
-rw-r--r--tests/baseline/10134
-rw-r--r--tests/baseline/10144
-rw-r--r--tests/baseline/10154
-rw-r--r--tests/baseline/10164
-rw-r--r--tests/baseline/10174
-rw-r--r--tests/baseline/10184
-rw-r--r--tests/baseline/10194
-rw-r--r--tests/baseline/10204
-rw-r--r--tests/baseline/10214
-rw-r--r--tests/baseline/10224
-rw-r--r--tests/baseline/10234
-rw-r--r--tests/baseline/10244
-rw-r--r--tests/baseline/10254
-rw-r--r--tests/baseline/10264
-rw-r--r--tests/baseline/10274
-rw-r--r--tests/baseline/10284
-rw-r--r--tests/baseline/10294
-rw-r--r--tests/cases/1001.dat10
-rw-r--r--tests/cases/1002.dat25
-rw-r--r--tests/cases/1030.dat24
-rw-r--r--tests/cases/1032.dat834
-rwxr-xr-xtests/confirm.py58
-rw-r--r--tests/parser.h65
-rwxr-xr-xtests/regress95
-rwxr-xr-xtests/regtest27
-rwxr-xr-xtests/runtests.py184
-rw-r--r--tests/textual.h34
-rw-r--r--textual.cc1045
-rw-r--r--textual.h46
-rw-r--r--timing.h62
-rw-r--r--tools/Makefile.am527
-rwxr-xr-xtools/autogen.sh (renamed from autogen.sh)0
-rwxr-xr-xtools/average26
-rw-r--r--tools/configure.ac427
-rw-r--r--tools/excludes47
-rwxr-xr-xtools/pre-commit61
-rwxr-xr-xtools/proof32
-rwxr-xr-xtools/push15
-rwxr-xr-xtools/rename.sh67
-rwxr-xr-xtools/speedcmp18
-rwxr-xr-xtools/times.sh6
-rw-r--r--util.h62
-rw-r--r--valexpr.cc1988
-rw-r--r--valexpr.h517
-rw-r--r--value.cc1696
-rw-r--r--value.h444
-rw-r--r--walk.cc911
-rw-r--r--walk.h751
-rw-r--r--xml.cc476
-rw-r--r--xml.h48
867 files changed, 213861 insertions, 26749 deletions
diff --git a/.gitignore b/.gitignore
index 18c7c771..43c726a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,70 +1,67 @@
-*.[oa]
-*.dSYM
+.timestamp
+*.backup
*.elc
-*.la
-*.lo
-*.loT
-*.o
+*.pyc
*~
-.deps/
-.libs/
-.svn
-/.deps
-/.libs
-/AUTHORS
-/COPYING
-/ChangeLog
-/Makefile
+/ABOUT-NLS
+/Makefile.am
/Makefile.in
/TAGS
-/acconf.h
/acconf.h.in
-/acconf.h.in~
/aclocal.m4
-/amounts.so
-/autom4te.cache
+/autogen.sh
+/autom4te.cache/
/config.guess
-/config.log
-/config.status
+/config.h.in
+/config.rpath
/config.sub
/configure
+/configure.ac
/depcomp
-/elc-stamp
/elisp-comp
/install-sh
+/intl/
/ledger
-/ledger-*
-/ledger.info
-/libtool
/ltmain.sh
-/make.deps
+/m4/
+/make.sh
/missing
-/pending
-/stamp-h1
+/po/
+/py-compile
+/src/system.hh.gch
/texinfo.tex
-AUTHORS
-INSTALL
-Makefile
-Makefile.in
-acconf.h
-acconf.h.in
-aclocal.m4
-autom4te.cache/
-config.guess
-config.log
-config.status
-config.sub
-configure
-depcomp
-doc/*.info
-elc-stamp
-elisp-comp
-install-sh
-ledger
-ledger.info
-libtool
-ltmain.sh
-missing
-stamp-h1
-texinfo.tex
+/version.m4
+
+*.[oa]
+*.l[oa]
+/*.tar.bz2
+/*.tar.gz
+/.deps/
+/.libs/
+/BaselineTests
+/Doxyfile.gen
+/Makefile
+/PyUnitTests
/RegressionTests
+/config.h
+/config.log
+/config.status
+/data_tests
+/doc/.dirstamp
+/doc/html/
+/doc/latex/
+/doc/ledger.info
+/doc/refman.pdf
+/doc/report/
+/expr_tests
+/libtool
+/math_tests
+/report_tests
+/shave
+/shave-libtool
+/stamp-h1
+/test/python/
+/tmpcvs*/
+/tmpwrk*/
+/util_tests
+/mkinstalldirs
diff --git a/.gitmodules b/.gitmodules
index 3a349c62..18e192aa 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
-[submodule "data"]
- path = data
- url = .
+[submodule "lib/utfcpp"]
+ path = lib/utfcpp
+ url = git://github.com/jwiegley/utfcpp.git
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index 8a0f1266..00000000
--- a/Makefile.am
+++ /dev/null
@@ -1,172 +0,0 @@
-EXTRA_DIST = LICENSE scripts ledger.vim sample.dat
-
-lib_LTLIBRARIES = libamounts.la libledger.la
-
-libamounts_la_CXXFLAGS =
-libamounts_la_SOURCES = \
- amount.cc \
- balance.cc \
- datetime.cc \
- value.cc
-if HAVE_BOOST_PYTHON
-libamounts_la_CXXFLAGS += -DUSE_BOOST_PYTHON=1
-endif
-if DEBUG
-libamounts_la_CXXFLAGS += -DDEBUG_LEVEL=4
-libamounts_la_SOURCES += debug.cc
-endif
-
-libledger_la_CXXFLAGS =
-libledger_la_SOURCES = \
- binary.cc \
- config.cc \
- csv.cc \
- derive.cc \
- emacs.cc \
- format.cc \
- journal.cc \
- mask.cc \
- option.cc \
- parser.cc \
- qif.cc \
- quotes.cc \
- reconcile.cc \
- report.cc \
- startup.cc \
- textual.cc \
- valexpr.cc \
- walk.cc \
- xml.cc
-if HAVE_EXPAT
-libledger_la_CXXFLAGS += -DHAVE_EXPAT=1
-libledger_la_SOURCES += gnucash.cc
-endif
-if HAVE_XMLPARSE
-libledger_la_CXXFLAGS += -DHAVE_XMLPARSE=1
-libledger_la_SOURCES += gnucash.cc
-endif
-if HAVE_LIBOFX
-libledger_la_CXXFLAGS += -DHAVE_LIBOFX=1
-libledger_la_SOURCES += ofx.cc
-endif
-if DEBUG
-libledger_la_CXXFLAGS += -DDEBUG_LEVEL=4
-endif
-libledger_la_LDFLAGS = -release 2.6.1
-
-pkginclude_HEADERS = \
- acconf.h \
- \
- amount.h \
- balance.h \
- datetime.h \
- value.h \
- debug.h \
- util.h \
- \
- binary.h \
- config.h \
- csv.h \
- derive.h \
- emacs.h \
- error.h \
- format.h \
- gnucash.h \
- journal.h \
- ledger.h \
- mask.h \
- option.h \
- parser.h \
- qif.h \
- ofx.h \
- quotes.h \
- reconcile.h \
- report.h \
- textual.h \
- timing.h \
- valexpr.h \
- walk.h \
- xml.h
-
-######################################################################
-
-bin_PROGRAMS = ledger
-ledger_CXXFLAGS =
-ledger_SOURCES = main.cc
-ledger_LDADD = $(LIBOBJS) libamounts.la libledger.la
-if HAVE_EXPAT
-ledger_CXXFLAGS += -DHAVE_EXPAT=1
-endif
-if HAVE_XMLPARSE
-ledger_CXXFLAGS += -DHAVE_XMLPARSE=1
-endif
-if HAVE_LIBOFX
-ledger_CXXFLAGS += -DHAVE_LIBOFX=1
-endif
-if DEBUG
-ledger_CXXFLAGS += -DDEBUG_LEVEL=4
-endif
-ledger_LDFLAGS = -static # for the sake of command-line speed
-
-info_TEXINFOS = ledger.texi
-
-######################################################################
-
-lisp_LISP = ledger.el timeclock.el
-dist_lisp_LISP = ledger.el timeclock.el
-
-######################################################################
-
-EXTRA_DIST += setup.py
-
-if HAVE_BOOST_PYTHON
-
-noinst_PROGRAMS = amounts.so
-amounts_so_SOURCES = amounts.cc fdstream.hpp
-
-amounts.so: amounts.cc libamounts.la
- CFLAGS="$(CPPFLAGS) -I$(srcdir) $(libamounts_la_CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)" \
- LDFLAGS="$(LDFLAGS) -L$(top_builddir) -L$(top_builddir)/.libs" \
- ARCHFLAGS="$(ARCHFLAGS)" SRCDIR="$(srcdir)" \
- python setup.py build --build-lib=$(top_builddir)
-
-install-exec-hook:
- CFLAGS="$(CPPFLAGS) -I$(srcdir) $(libamounts_la_CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)" \
- LDFLAGS="$(LDFLAGS) -L$(top_builddir) -L$(top_builddir)/.libs" \
- ARCHFLAGS="$(ARCHFLAGS)" SRCDIR="$(srcdir)" \
- python setup.py install --prefix=$(prefix) --root=$(DESTDIR)/
-
-endif
-
-######################################################################
-
-TESTS = RegressionTests
-
-DISTCLEANFILES = RegressionTests
-
-RegressionTests:
- echo "exit 0" > $@
- chmod 755 $@
-
-######################################################################
-
-copy-sources:
- -mkdir /tmp/ledger
- rsync -av --delete $(srcdir)/.git/ /tmp/ledger/.git/
- (cd /tmp/ledger; git reset --hard HEAD; git clean -x -d -f)
-
-release: copy-sources
- (cd /tmp/ledger; ./acprep && \
- make -j3 \
- CPPFLAGS="-I/usr/local/include -I/opt/local/include" \
- LDFLAGS="-L/usr/local/lib -L/opt/local/lib" \
- DISTCHECK_CONFIGURE_FLAGS="--disable-dependency-tracking")
-
-release-distcheck: copy-sources
- (cd /tmp/ledger; ./acprep && \
- make -j3 distcheck \
- CPPFLAGS="-I/usr/local/include -I/opt/local/include" \
- LDFLAGS="-L/usr/local/lib -L/opt/local/lib" \
- DISTCHECK_CONFIGURE_FLAGS="--disable-dependency-tracking")
-
-# Makefile.am ends here
diff --git a/README-1ST b/README-1ST
new file mode 100644
index 00000000..a56e4782
--- /dev/null
+++ b/README-1ST
@@ -0,0 +1,120 @@
+
+===============================================================================
+
+ README FIRST!!!
+
+To build this code after doing a Git clone, run:
+
+ $ ./acprep update
+
+If you try to configure and build on your own, you are almost certainly going
+to run into problems. In future, you can run this command again and again,
+and it will keep you updated to the very latest version.
+
+===============================================================================
+
+ NOTE FOR MAC OS X USERS
+
+To build and install Ledger on the Mac requires several dependencies. If you
+are a MacPorts user, you can install these dependencies very simply using:
+
+ $ ./acprep dependencies
+
+Once this is done, I recommend building both debug and optimized versions of
+Ledger, in a subdirectory of your source tree named 'build' (which acprep will
+manage for you, you simply need to make it):
+
+ $ mkdir build
+ $ ./acprep opt make
+ $ ./acprep debug make
+
+Now install the optimized version, but know that you have 'build/debug/ledger'
+available for testing and more useful bug reports.
+
+===============================================================================
+
+ IF YOU HAVE CONFIGURE OR BUILD PROBLEMS
+
+The first order of business if acprep update doesn't work is to find out where
+things went wrong. So follow these steps to produce a bug report I can track
+down easily:
+
+ $ ./acprep --debug update # shows what acprep was thinking
+ $ <edit config.log> # shows what configure was thinking
+
+With the contents of config.log, and the output from acprep --debug update,
+it's usually fairly obvious where things have gone astray.
+
+===============================================================================
+
+ F.A.Q.
+
+ - Q: The build fails saying it can't find utf8.h
+
+ A: You didn't run ./acprep update.
+
+ ----------------------------------------------------------------------
+
+ - Q: Configure fails saying it can't find boost_regex
+
+ A: Look in config.log and search for "boost_regex", then scroll down a bit
+ until you see the exact compile error. Usually it's failing because
+ your include directory is different from anything acprep is expecting to
+ see. It could also be failing because your Boost libraries have a
+ custom "suffix" on them.
+
+ Let's say your Boost was installed in ~/boost, and every library has the
+ suffix '-xgcc42'. This is what you would run:
+
+ CPPFLAGS=-I$HOME/boost acprep --boost=xgcc42 update
+
+ ----------------------------------------------------------------------
+
+ - Q: Configure fails saying it can't find MPFR
+
+ A: You need MPFR version 2.4.0 or higher. This version does not come with
+ most Debian distributions, so you will need to build it.
+
+ ----------------------------------------------------------------------
+
+ - Q: I'm seeing a segfault deep inside the boost_regex code!
+
+ A: Actually, the real segfault is in libstdc++'s facet code. It's being
+ caused by using a debug Boost with a non-debug build of Ledger, or
+ vice-versa.
+
+ ----------------------------------------------------------------------
+
+ - Q: Something else fails, or Ledger crashes on startup
+
+ A: This, I am most interested in hearing about. Please e-mail me a copy of
+ config.log and your build log to <johnw@newartisans.com>. Also, if
+ Ledger is crashing, try running it under gdb like so:
+
+ $ gdb ledger
+ (gdb) run <ARGS TO LEDGER>
+ ... runs till crash ...
+ (gdb) bt
+
+ Send me that backtrace output, and the output from "ledger --version".
+
+ ----------------------------------------------------------------------
+
+ - Q: Whenever I try to use the Python support, I get a segfault
+
+ A: Make sure that the boost_python library you linked against is using the
+ exact same Python as the Ledger executable. In particular I see this
+ bug on OS X systems where boost_python is linked against the default
+ Python, while Ledger is linked against the version provided by MacPorts.
+
+ Solution: Use one or the other. If you prefer the system Python, run
+ "port deactivate -f python26", to get MacPorts' version out of the way.
+ You'll then need to delete the Ledger binary and run "make" to relink
+ it.
+
+ ----------------------------------------------------------------------
+
+ - Q: When I run "make check", the Python unit tests always crash
+
+ A: This can happen for the same reason as above. It can also happen if you
+ have ICU support enabled. This is a bug I'm still trying to track down.
diff --git a/README.textile b/README.textile
new file mode 100644
index 00000000..2a730746
--- /dev/null
+++ b/README.textile
@@ -0,0 +1,162 @@
+h1. Ledger: Command-Line Accounting
+
+Ledger is a powerful, double-entry accounting system that is accessed from the
+UNIX command-line. This may put off some users, since there is no flashy UI,
+but for those who want unparalleled reporting access to their data there are
+few alternatives.
+
+h2. For the Impatient
+
+I know, you just want to build and play. If you have all the dependencies
+installed (see below), then simply do this:
+
+<pre>
+git clone git://github.com/jwiegley/ledger.git
+cd ledger && ./acprep update # Update to the latest, configure, make
+</pre>
+
+Now try your first ledger command:
+
+<pre>
+./ledger -f doc/sample.dat reg
+</pre>
+
+h2. To the Rest
+
+If you're reading this file, you have in your hands the Bleeding Edge. This
+may very well *not* be what you want, since it's not guaranteed to be in a
+functionally complete state. It's under active development, and may change in
+any way at any time.
+
+What you may prefer is the current stable release, or the current beta branch.
+The *BETA* is what I prefer people use, since I still have a chance to fix
+major bugs that you find. Just e-mail me, or post to the mailing list,
+they'll become a part of my work list.
+
+|*CURRENT*|@git checkout master@|
+|*BETA*|@git checkout -b maint origin/maint@|
+|*RELEASE*|@git checkout v2.6.1@|
+
+There are also several topic branches which contain experimental features,
+though none of these are guaranteed to compile. Best to chat with me on
+"IRC":irc//irc.freenode.net/ledger or via the
+"mailing list":http://groups.google.com/group/ledger-cli before going too
+much further with those.
+
+h2. Dependencies
+
+If you wish to proceed in this venture, you'll need a few dependencies. The
+easiest way to get them for your platform is to run:
+
+<pre>
+./acprep dependencies
+</pre>
+
+If that doesn't completely work, read on.
+
+h3. For building the current master branch
+
+|_.Library|_.Min.Ver.|_.When needed|
+|Boost|1.35||
+|GMP|4.2.2||
+|MPFR|2.4.0||
+|gettext|0.17|_optional_|
+|libedit|20090111-3.0|_optional_|
+|Python|2.4|_optional_|
+|cppunit|1.12.1|_optional_, for @make check@|
+|doxygen|1.5.7.1|_optional_, for @make docs@|
+|graphviz|2.20.3|_optional_, for @make docs@|
+|texinfo|4.13|_optional_, for @make docs@|
+|lcov|1.6|_optional_, for @make report@, used with @./acprep gcov@|
+|sloccount|2.26|_optional_, for @make sloc@|
+
+h3. For building the current @maint@ branch
+
+|_.Library|_.Min.Ver.|_.When needed|
+|GMP|4.2.2||
+|pcre|7.7||
+|libofx|0.8.3|_optional_|
+|expat|2.0.1|_optional_|
+|libxml2|2.7.2|_optional_|
+
+h3. MacPorts
+
+If you build stuff using MacPorts on OS X, as I do, here is what you would
+run:
+
+<pre>
+sudo port install -f automake autoconf libtool python26
+ libiconv +universal zlib +universal gmp +universal
+ mpfr +universal ncurses +universal ncursesw +universal
+ gettext +universal libedit +universal boost-jam
+ boost +st+python26+icu cppunit texlive doxygen graphviz
+ texinfo lcov sloccount
+</pre>
+
+You can even just install the current Ledger *RELEASE* directly:
+
+<pre>
+sudo port install ledger
+</pre>
+
+h3. Ubuntu
+
+If you're going to be build on Ubuntu, @sudo apt-get install ...@ the
+following packages (current as of Ubuntu Hardy):
+
+<pre>
+sudo apt-get install build-essential libtool autoconf automake \
+ zlib1g-dev libbz2-dev python-dev bjam cvs gettext libgmp3-dev \
+ libmpfr-dev libboost1.35-dev libboost-regex1.35-dev \
+ libboost-date-time1.35-dev libboost-filesystem1.35-dev \
+ libboost-python1.35-dev texinfo lcov sloccount
+</pre>
+
+Or, for Ubuntu Karmic:
+
+<pre>
+sudo apt-get install build-essential libtool autoconf automake \
+ texinfo python-dev zlib1g-dev libbz2-dev libgmp3-dev \
+ bjam gettext cvs libboost1.40-dev libboost-regex1.40-dev \
+ libboost-date-time1.40-dev libboost-filesystem1.40-dev \
+ libmpfr-dev
+</pre>
+
+h2. Building
+
+The next step is preparing your environment for building. While you can use
+@autogen.sh@, ./configure and make, I've prepared a script that does a lot more
+of the footwork for you:
+
+<pre>
+./acprep update
+# or, if you want to use the Boost libraries with suffix -mt, install in
+# $HOME/local and build with 2 processes in parallel
+./acprep update --boost=-mt -- --prefix=$HOME/local -j2
+</pre>
+
+Please read the contents of @config.log@ if the configure step fails. Also,
+see the @help@ command to @acprep@, which explains some of its many options.
+It's pretty much the only command I run for configuring, building and testing
+Ledger.
+
+You can run @make check@ to confirm the result, and @make install@ to install.
+
+If you have extra CPU cycles to burn, try @./acprep proof@, which provides the
+most thorough shakedown of a healthy source tree.
+
+h2. Resources
+
+Now that you're up and running, here are a few resources to keep in mind:
+
+|Home page|"http://www.newartisans.com/software/ledger.html":http://www.newartisans.com/software/ledger.html|
+|IRC channel|"#ledger on irc.freenode.net":irc://irc.freenode.net/ledger|
+|Mailing List / Forum|"http://groups.google.com/group/ledger-cli":http://groups.google.com/group/ledger-cli|
+|GitHub project page|"http://github.com/jwiegley/ledger":http://github.com/jwiegley/ledger|
+|Buildbot status|"http://www.newartisans.com:9090":http://www.newartisans.com:9090|
+|Ohloh code analysis|"http://www.ohloh.net/projects/ledger":http://www.ohloh.net/projects/ledger|
+
+If you have ideas you'd like to share, the best way is either to e-mail me a
+patch (I prefer attachments over pasted text), or to get an account on GitHub.
+Once you do, fork the "Ledger project":http://github.com/jwiegley/ledger, hack
+as much as you like, then send me a pull request via GitHub.
diff --git a/TODO b/TODO
deleted file mode 100644
index 68993ae0..00000000
--- a/TODO
+++ /dev/null
@@ -1,1088 +0,0 @@
-LEDGER -*- mode: org; fill-column: 78 -*-
-
-#+STARTUP: overview
-#+ARCHIVE: TODO-OLD::
-#+SEQ_TODO: TODO(@) STARTED(@) WAITING(@) DELEGATED(@) | DONE(@) DEFERRED(@) CANCELLED(@) WONTFIX(@) WORKSFORME(@) INVALID(@) DUPLICATE(@) NOTE
-#+TAGS: EMACS(e) FEATURE(f) DOCS(d) WEBSITE(w) BUILD(b)
-#+CATEGORY: Ledger
-
-* DONE [#B] -e doesn't seem to work for providing an end date
- - State "DONE" [2008-04-04 Fri 14:34] \\
- There was a problem with the -e date parsing. I now interpret "-e june"
- to mean that you want the report to end AT June, rather than IN June.
- :DATA:
-2008/03/20 Grocery Store
- Travel:Home 2.3 miles
- Wear & Tear:Car
-
-2008/03/31 Office
- Travel:Work 16 miles
- Wear & Tear:Car
-
-2008/04/01 Office
- Travel:Work 16 miles
- Wear & Tear:Car
-
-2008/04/02 Office
- Travel:Work 16 miles
- Wear & Tear:Car
-
-2008/04/03 Office
- Travel:Work 16 miles
- Wear & Tear:Car
-
-2008/04/04 Office
- Travel:Work 16 miles
- Wear & Tear:Car
- :END:
- :OUTPUT:
-$ ledger -f /tmp/mileage.ledger -b 2008-03-31 reg travel
-2008/03/31 Office Travel:Work 16.7 miles 16.7 miles
-2008/04/01 Office Travel:Work 16.7 miles 33.4 miles
-2008/04/02 Office Travel:Work 16.7 miles 50.1 miles
-2008/04/03 Office Travel:Work 16.7 miles 66.8 miles
-2008/04/04 Office Travel:Work 16.7 miles 83.5 miles
-$ ledger -f /tmp/mileage.ledger -b 2008-03-31 -e 2008-04-05 reg travel
-$
- :END:
- Shouldn't that last command give me the same output as the former?
- :PROPERTIES:
- :Submitter: drewr <#ledger>
- :Version: 2.6
- :Ticket: 36
- :ID: 1DE6FB08-93D2-47C8-A5A3-3379BA76360D
- :END:
- [2008-04-04 Fri]
-* DONE [#A] -p "this month" doesn't work at all anymore
- - State "DONE" [2008-07-17 Thu 18:14] \\
- This has been fixed, and represents a very major set of fixes to date
- handling in general. Thanks to Nathan for hitting the nail on the head.
- - State "TODO" [2008-04-05 Sat 18:57] \\
- Nathan Jones <nathanj@insightbb.com> writes:
- > The patch fixes a command that I have aliased to show my last two months
- > of transactions: `ledger -d 'd>=[last month]' reg checking`
- >
- > The problem is that the 'last month' would get parsed as 1970/1/1, so it
- > would show every transaction.
- :OUTPUT:
-~ $ DEBUG_CLASS=ledger.config.predicates *ledger -p "this month" reg cash
-Predicate: d>=[1969/12/31]&d<[1970/01/31]&/(?:cash)/
- :END:
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 38
- :Attachments: 289.patch
- :ID: 0CF00621-31C4-4E5A-B260-78B4DA8C3616
- :END:
- [2008-04-04 Fri]
-* DONE [#A] Cannot sort by reverse time
- - State "DONE" [2008-07-19 Sat 16:52]
- When I specify `--sort -d`, I get:
- :OUTPUT:
-~/src/ledger $ ledger -b 2008/07 --sort -d reg cash
-While computing value expression:
- -date
- ^^^^^
-Error: Cannot negate a date/time
- :END:
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6.0.90
- :Ticket: 202
- :ID: CB97253A-581E-49D0-98D4-3BC5B0616A42
- :END:
- [2008-07-17 Thu]
-* DONE [#B] Command results in assertion failure
- - State "DONE" [2008-07-17 Thu 17:44]
- The command is:
- :SCRIPT:
-ledger -s bal --sort O wedding
- :END:
- This is against my own ledger file.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 23
- :ID: AB684BBE-F093-4F77-BCFB-2F4E0D60AA9C
- :END:
- [2007-12-10 Mon]
-* DONE [#A] Core dump on simple input.
- - State "DONE" [2008-07-17 Thu 17:38]
- :DATA:
-2008/01/03=2007/12/28 * Sell -- RHT -- RED HAT INC CA TAUX DE CHANGE .96590
- Assets:Investments:RBC-Broker:Account-RSP -4.00 RHT @ 21.14 CAD
- Expenses:Financial:Commissions 9.95 USD @ .96590 CAD
- Assets:Investments:RBC-Broker:Account-RSP 72.06 CAD
- :END:
- :PROPERTIES:
- :Submitter: Martin Blais <blais@furius.ca>
- :Version: 2.6
- :Ticket: 56
- :ID: 843B6A53-C3C2-45BB-A92C-558AF6F02014
- :END:
- [2008-04-07 Mon]
-* DONE [#B] Coredump.
- - State "DONE" [2008-07-17 Thu 17:50]
- :DATA:
-2008/01/02 * Sell -- on 2007/12/27 -- CRA -- APPLERA CORP COM CELERA GROUP CA EXCHANGE RATE .96760
- Assets:Investments:RBC-Broker:Account-CAD -8.00 CRA @ 16.93 USD ; lot:ba8c951719fd
- Expenses:Financial:Commissions 9.95 USD
- Expenses:Financial:Fees 0.01 USD
- Assets:Investments:RBC-Broker:Account-CAD 125.48 USD
- Assets:Investments:RBC-Broker:Account-CAD -125.48 USD ; @ 0.96760 USD
- Assets:Investments:RBC-Broker:Account-CAD 121.41 CAD
- :END:
- :PROPERTIES:
- :Submitter: Martin Blais <blais@furius.ca>
- :Version: 2.6
- :Ticket: 50
- :ID: A18B37A4-68DB-4F3A-92D5-3962D010CA0B
- :END:
- [2008-04-06 Sun]
-* DONE [#A] crash
- - State "DONE" [2008-07-17 Thu 17:39]
- :DATA:
-2007-12-31 * Start of year / Opening balances.
- Assets:Investments:HSBC-Broker 1000 USD @ 101.00 JPY
- Equity:Opening-Balances:Cost -1000 USD
- :END:
- :PROPERTIES:
- :Submitter: Martin Blais <blais@furius.ca>
- :Version: 2.6
- :Ticket: 177
- :ID: 45605775-F9E3-4C83-8BF2-616905178E82
- :END:
- [2008-04-12 Sat]
-* DONE [#B] Crash on input -- spurious comma
- - State "DONE" [2008-07-17 Thu 17:49]
- :DATA:
-2008/02/25 * bla bla bnla
- Assets:Fixed:Home 235000.00 CAD
- Expenses:Home:Acquisition:Escrow -82250.00 CAD
- Liabilities:RBC:Mortgage:Loan -1.00 CAD, ; opening of account
- Liabilities:RBC:Mortgage:Loan -152749.00 CAD
- :END:
- :PROPERTIES:
- :Submitter: Martin Blais <blais@furius.ca>
- :Version: 2.6
- :Ticket: 48
- :ID: 517CB118-49A5-42B2-ACFD-1A63DCF163AA
- :END:
- [2008-04-06 Sun]
-* DONE [#A] Crash on input.
- - State "DONE" [2008-07-17 Thu 17:38]
- - State "TODO" [2008-04-06 Sun 10:23] \\
- Martin Blais <blais@furius.ca> writes:
- > I think that the bug is related to the missing currency after the @
- > sign.
- :DATA:
-;; Assets:Investments:HSBC-Broker ------------------------------------------------------------
-
-2007/12/31 * Start of year / Opening balances.
- Assets:Investments:HSBC-Broker 100 IVV
- Assets:Investments:HSBC-Broker -15360.60 USD ; cost basis of older purchase
- Equity:Opening-Balances
-
-2008/01/03 * Dividends received for IVV holding.
- Assets:Investments:HSBC-Broker 79.79 USD
- Income:Interest:Dividends
-
-
-2008/02/04 * Sell 100 IVV - on 2008/01/30
- Assets:Investments:HSBC-Broker -100 IVV @ 136.2901
- Assets:Investments:HSBC-Broker -13629.01 USD
- Expenses:Financial:Commissions 24.99 USD
- Expenses:Financial:Fees 0.15 USD
- Expenses:Financial:Fees 2.00 USD
- :END:
- :OUTPUT:
-banane:~/__accounting/.../rbcinv/invest$ ledger -f /tmp/b -V register hsbc:broker
-Segmentation fault (core dumped)
-banane:~/__accounting/.../rbcinv/invest$
- :END:
- :PROPERTIES:
- :Submitter: Martin Blais <blais@furius.ca>
- :Version: 2.6
- :Ticket: 46
- :ID: 703505C9-B702-4139-B64A-FD3CF592E720
- :END:
- [2008-04-06 Sun]
-* DONE [#A] Crash on input.
- - State "DONE" [2008-07-17 Thu 17:38]
- :DATA:
-2008/01/02 ! Sell -- on 2007/12/27 -- CRA -- APPLERA CORP COM CELERA GROUP CA EXCHANGE RATE .96760
- Assets:Investments:RBC-Broker:Account-CAD -8.00 CRA @ 16.93 USD
- Assets:Investments:RBC-Broker:Account-CAD 121.41 CAD
- Expenses:Financial:Commissions -9.95 USD
- Expenses:Financial:Fees -0.01 USD
- :END:
- :PROPERTIES:
- :Submitter: Martin Blais <blais@furius.ca>
- :Version: 2.6
- :Ticket: 47
- :ID: B2B79746-5E3B-40D3-B6ED-CCF27364DD5F
- :END:
- [2008-04-06 Sun]
-* DONE [#B] Crash on input.
- - State "DONE" [2008-07-17 Thu 17:45]
- :DATA:
-2008/01/02 ! Sell -- on 2007/12/27 -- CRA -- APPLERA CORP COM CELERA GROUP CA EXCHANGE RATE .96760
- Assets:Investments:RBC-Broker:Account-CAD -8.00 CRA @ 16.93 USD
- Assets:Investments:RBC-Broker:Account-CAD 21.41 CAD
- Expenses:Financial:Commissions -9.95 USD
- Expenses:Financial:Fees -0.01 USD
- :END:
- :PROPERTIES:
- :Submitter: Martin Blais <blais@furius.ca>
- :Version: 2.6
- :Ticket: 45
- :ID: 93CFAFEB-46EA-4E47-8F0A-069309D6EE3A
- :END:
- [2008-04-06 Sun]
-* DONE [#B] Crash reading .timelog file
- - State "DONE" [2008-07-17 Thu 18:08]
- 2.6b aborts if the last entry is the timelog is an "in" event.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 128
- :ID: C7A32276-11A7-44F1-99CD-6F0CA7330340
- :END:
- [2008-04-11 Fri]
-* DONE [#A] Dates (used with -b -e and -p parameters) are broken
- - State "DONE" [2008-07-17 Thu 06:20] \\
- Patch checked in. Thanks, Nathan!
- - State "TODO" [2008-04-06 Sun 21:59] \\
- Nathan Jones <nathanj@insightbb.com> writes:
- > The attached patch plus the one in #38 should fix this.
- The release (2.6.0.90) doesn't seem to properly parse dates. The svn
- version (rev. 1048) works fine for full dates (yyyy/mm/dd) with the -b -e
- params but nothing else works. For example in the following only the last
- one works:
- :SCRIPT:
-ledger -f my.ledger -b mar -e apr print
-ledger -f my.ledger -b 03/01 -e -04/01 apr print
-ledger -f my.ledger -b 03/01 -e 04/01 print
-ledger -f my.ledger -b 08/03/01 -e 08/04/01 print
-ledger -f my.ledger -b 2008/03/01 -e 2008/04/01 print
- :END:
- The -p param doesn't seem to work at all.
- :PROPERTIES:
- :Submitter: kmt <kmt@ftml.net>
- :Version: 2.6.0.90
- :Ticket: 49
- :Attachments: 290.patch
- :ID: A95B2E0F-095D-4314-BC4D-3CEC42203FB1
- :END:
- [2008-04-06 Sun]
-* DONE [#B] Do not adjust display precision when parsing a pricing entry
- - State "DONE" [2008-09-17 Wed 05:12]
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6.0.90
- :Ticket: 206
- :ID: 7E5D2A6C-A15F-4BC8-A851-04A48E3E30F4
- :END:
- [2008-07-28 Mon]
-* DONE [#C] Entry command doesn't match debit account when description is unmatched
- - State "DONE" [2008-07-20 Sun 20:32]
- I think I've isolated a bug with the entry command where I get "Equity"
- instead of a valid debit account:
- :OUTPUT:
-$ ledger entry 2008/07/18 "Pei Wei" food 20 checking
-
-2008/07/18 Pei Wei
- Expenses:Food:Out $ 20.00
- Assets:Checking
-
-$ ledger entry 2008/07/18 "Foo Bar" food 20 checking
-
-2008/07/18 Foo Bar
- Expenses:Food $ 20.00
- Equity
- :END:
-
- The first command proves that ledger understands I have an `Assets:Checking`
- account. That's because I already have entries for `Pei Wei`.
-
- If I enter a description that doesn't match a previous entry, it doesn't
- match `checking` to `Assets:Checking`.
- :PROPERTIES:
- :Submitter: drewr <#ledger>
- :Version: 5fbec3582319ca6423a43c9125842be5f969e8ee
- :Ticket: 203
- :ID: FF8CE4C5-03B3-4FCA-85BD-52A9DB191B4B
- :END:
- [2008-07-18 Fri]
-* DONE [#A] Entry command produces two liability transactions
- - State "DONE" [2008-07-17 Thu 22:01]
- - State "TODO" [2008-05-03 Sat 22:27] \\
- This is being a real problem for drewr, arete and pll! This one gets fixed
- for 2.6.1.
- :OUTPUT:
-arete$ ledger entry 2007/11/11 safeway groceries \$10.00 american
-
-2007/11/11 Safeway
- Expenses:Groceries $10.00
- Liabilities:American Express $-30.17
- Liabilities:American Express $20.17
- :END:
- :PROPERTIES:
- :Submitter: Will Glozer <will@glozer.net>
- :Version: 2.6
- :Ticket: 8
- :ID: D7DD54D7-8870-4D6D-92A0-90717692F8F2
- :END:
- [2007-11-12 Mon]
-* DONE [#B] Expressions don't work.
- - State "DONE" [2008-07-17 Thu 21:37]
- - State "TODO" [2008-04-12 Sat 14:58] \\
- Martin Blais <blais@furius.ca> writes:
- > Note the typo in the error too: "evalute" -> "evaluate".
- :DATA:
-2007-12-31 * Start of year / Opening balances.
- Assets:Investments:HSBC-Broker 1000 USD
- Equity:Opening-Balances:Cost -101000 JPY @ 1/101.00 USD
- :END:
- :PROPERTIES:
- :Submitter: Martin Blais <blais@furius.ca>
- :Version: 2.6
- :Ticket: 178
- :ID: DA9F2346-CD90-4E22-B2F0-2670532456BA
- :END:
- [2008-04-12 Sat]
-* DONE [#B] Getting an abort with a self-referential pricing statement
- - State "DONE" [2008-07-17 Thu 17:51] \\
- Getting this to work correctly is going to need more work (which has already
- been logged as another bug).
- :DATA:
-2008/01/02 sell
- Assets:Investments 130.41 CAD @ 1.03352277 CAD
- Assets:Investments -8.00 CRA @ 16.93 USD
- :END:
- Passing this through the reg command produces a SIGABRT.
- :PROPERTIES:
- :Submitter: Martin Blais <blais@furius.ca>
- :Version: 2.6
- :Ticket: 51
- :ID: A21E4DCC-6112-441F-B76D-95CF47BA658D
- :END:
- [2008-04-06 Sun]
-* DONE [#B] Ignore [TEXT] in a transaction which does not specify a date
- - State "DONE" [2008-09-17 Wed 05:10] \\
- Fixed, by simply ignoring when something that looks [TEXT] in a transaction
- note fails to parse as a date.
- The following data contains a link, not an effective date.
- :DATA:
-2008/08/11 (08/13/2008) DD/BR #337756 Q35 TONAWANDA, NY
- Liabilities:Visa -3.63
- Assets:Company:AGIL1892 ; /PersMealsBreakf/ [[file:///home/rladams/doc/Album/Receipts/20080815131347.jpg]]
- :END:
- :PROPERTIES:
- :ID: 96DDA4B9-E216-4C7A-8D0E-02B0F39CA256
- :END:
- [2008-08-27 Wed]
-* DONE [#B] Install patches for Ledger 2.6 from Simon Michael
- - State "DONE" [2008-07-17 Thu 21:41] \\
- I'm only taking the first patch for 2.6. The other two need a bit more
- polish before I would put them in the standard distro, instead of just
- posting them to the Wiki or some such.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 60
- :ID: 0C311A59-701A-4D30-BBDB-924F12878724
- :Attachments: sm001.patch sm002.patch sm004.patch
- :END:
- [2008-04-11 Fri]
-* DONE [#A] ledger 2.6 shows no timelog entries
- - State "DONE" [2008-07-17 Thu 19:08]
- - State "TODO" [2008-08-18 Mon 02:15] \\
- Simon Michael <simon@joyful.com> writes:
- > And if ends with a "i" record, ledger gives a bus error. This is on
- > leopard.
- Ledger 2.5 shows entries in my timelog file, but 2.6.1-pre shows none. There
- is no parse error.
- :PROPERTIES:
- :Submitter: Simon Michael <simon@joyful.com>
- :Version: 2.6.1b
- :Ticket: 57
- :ID: C13F0BDF-4E15-442E-BBB7-265B0A37457C
- :END:
- [2008-04-09 Wed]
-* DONE [#A] Ledger fails to balance a simple entry
- - State "DONE" [2008-07-28 Mon 02:05] \\
- This was quite the nasty little bug.
- I just installed v2.6.1 and ledger reports errors with some transactions
- that were fine with v2.5:
- :OUTPUT:
-[21:51:49 vinod]:~/src/ledger $ ledger --version
-Ledger 2.6.1, the command-line accounting tool
-
-[21:51:55 vinod]:~/src/ledger $ ledger bal
-While balancing entry:
- 2007/02/02 RD VMMXX
- Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
- Income:Dividends:Vanguard:VMMXX $-0.35
-Unbalanced remainder is:
- $-0.35
-Error: "/home/vinod/data/ledger.dat", line 52379: Entry does not balance
- :END:
- :PROPERTIES:
- :Submitter: Vinod Kurup <vvkurup@gmail.com>
- :Version: 2.6.1b
- :Ticket: 205
- :ID: 0CA014F9-E309-4840-9085-71EC1F46DEC1
- :END:
- [2008-07-28 Mon]
-* DONE [#B] ledger SVN doesn't compile on freebsd-8
- - State "DONE" [2008-03-17 Mon 16:22] \\
- Clemens writes:
- > Just for the record, there's a fix:
- :PATCH:
-diff --git a/ledger-2.6.0.90/datetime.h b/ledger-2.6.0.90/datetime.h
---- a/ledger-2.6.0.90/datetime.h
-+++ b/ledger-2.6.0.90/datetime.h
-@@ -96,7 +96,7 @@ class date_t
- operator bool() const {
- return when != 0;
- }
-- operator std::time_t() const {
-+ operator std::time_t() /*const*/ {
- return when;
- }
- operator std::string() const {
- :END:
- > Let's you compile and install.
- - State "DONE" [2008-03-14 Fri 21:32] \\
- This is a known bug that was fixed in 2.6. If you need a back-patch for
- 2.4.1, please let me know.
- We have ledger-2.4 in the ports, but it segfaults on freebsd-8 (the current
- dev version of the OS). The backtrace is incoherent, because the libs are
- stripped and we have no symbols. Anyway, a sane person would want a more
- recent ledger. The tarball exhibits the exact same problem as the one from
- SVN:
- :OUTPUT:
-'uname -rims' -> FreeBSD 8.0-CURRENT i386 GENERIC
-'gcc --version' -> gcc (GCC) 4.2.1 20070719 [FreeBSD]
-
-/src/bulk/ledger/trunk
-0 $ gmake
-gmake all-am
-gmake[1]: Entering directory `/home/src/bulk/ledger/trunk'
-/usr/local/bin/bash ./libtool --tag=CXX --mode=compile g++ -DHAVE_CONFIG_H -I. -I/l/include -g -O2 -c -o libamounts_la-amount.lo `test -f 'amount.cc' || echo './'`amount.cc
- g++ -DHAVE_CONFIG_H -I. -I/l/include -g -O2 -c amount.cc -fPIC -DPIC -o .libs/libamounts_la-amount.o
-In file included from amount.h:13,
- from amount.cc:1:
-datetime.h: In function 'long int operator-(const date_t&, const date_t&)':
-datetime.h:141: error: conversion from 'date_t' to 'long int' is ambiguous
-datetime.h:99: note: candidates are: date_t::operator time_t() const
-datetime.h:96: note: date_t::operator bool() const
-gmake[1]: *** [libamounts_la-amount.lo] Error 1
-gmake[1]: Leaving directory `/home/src/bulk/ledger/trunk'
-gmake: *** [all] Error 2
- :END:
-
- I know C and i can do some gdb(1), but i don't have the C++ knowledge to
- even fix this one. It looks not all that complicated. Maybe a little patch
- could help the C++ compiler to figure out the type inference.
-
- I used emacs for quite some time, but got annoyed with its ancient lisp. So
- using the common lisp version is currently not an option for me, and without
- emacs one has to type way to much for some little reports. Could you please
- bring the C++ version into a usable state again? perhaps it's not that much
- work?
- :PROPERTIES:
- :Submitter: Clemens <finetouch>
- :Version: 2.4.1
- :Ticket: 34
- :ID: C1BE11BD-958D-4E67-8B85-5DA14CD375B4
- :END:
- [2008-03-14 Fri]
-* DONE [#B] ledger.el requires an absolute pathname for the ledger-binary-path :EMACS:
- - State "DONE" [2008-07-17 Thu 22:09]
- This caused me pain after a ledger upgrade. "ledger" should be sufficient if
- it's in the path.
- :PROPERTIES:
- :Submitter: Simon Michael <simon@joyful.com>
- :Version: 2.6
- :Ticket: 199
- :ID: 7D40038A-DEED-47FA-8D02-0951E94CA175
- :END:
- [2008-07-12 Sat]
-* DONE [#A] Make -e use an inclusive end date, and -E an exclusive one
- - State "DONE" [2008-07-17 Thu 06:22] \\
- -e has been reverted back to its old behavior, to avoid confusing people.
- Right now (as of today) -e was made exclusive, but this isn't right; I need
- another option for exclusivity.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 37
- :ID: A440BB5E-072B-4C75-A235-C551EA090F81
- :END:
- [2008-04-04 Fri]
-* DONE [#A] Marking a transaction cleared may delete text in ledger-mode :EMACS:
- - State "DONE" [2008-07-18 Fri 02:28]
- I started the groundwork for this, now I just have to add code to insert
- whitespace if needed to keep each transaction valid.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 70
- :ID: 0EB5602F-66BE-46C0-8A74-5EB5DBAF2E07
- :END:
- [2008-04-11 Fri]
-* DONE [#C] Merge Levin's changes into v2.6.1b
- - State "DONE" [2008-08-26 Tue 10:11]
- These are from http://github.com/levindu/ledger
- :PROPERTIES:
- :ID: C9167249-98C3-4C7E-8076-35B81A580B38
- :END:
- [2008-08-21 Thu]
-* DONE [#C] Multiple commodities in gnucash crash ledger
- - State "DONE" [2008-07-17 Thu 21:26]
- - State "TODO" [2008-03-27 Thu 19:54] \\
- I still have to review the patch and make the changes, before this gets
- closed.
- - State "TODO" [2008-03-27 Thu 15:20] \\
- slanack writes:
- > The proposed Fix works for me. The problem was that <split:quantity>
- > received the `transaction commodity' instead of the correct `account
- > commodity'. There should really be a check if the account commodity has
- > been defined.
- I am using transactions between accounts with different base commodities in
- gnucash. Ledger reports a segfault when reading the gnucash file and using
- the command `print`.
- :PROPERTIES:
- :Submitter: slanack
- :Version: 2.6.0.90
- :Ticket: 35
- :ID: DAAF3481-1B7A-4F4A-9EC6-575104655B1B
- :Attachments: gnucash.cc.patch gnucash-minimal.xml
- :END:
- [2008-03-23 Sun]
-* DONE [#C] My "bal" command is broken again
- - State "DONE" [2008-07-17 Thu 21:22]
- :OUTPUT:
-~/Reference/Computing/Systems/Linux $ bal
- 3,848.34
- EC 450.05 Assets
-Error: Cannot compare amounts with different commodities: EC and $
- :END:
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 66
- :ID: 8159EF00-B95D-4E83-9927-7DB461CD2CC9
- :END:
- [2008-04-11 Fri]
-* DONE [#A] Reconciling is broken again; I need a way to verify Emacs output :EMACS:
- - State "DONE" [2008-07-17 Thu 23:40] \\
- Reconciling is now line-based in 2.6.1, not character based (which has serious
- issues with UTF-8 at the moment).
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 64
- :ID: 7A8C49FB-F9B8-4ECF-8720-9E29559F3CA6
- :END:
- [2008-04-11 Fri]
-* DONE [#C] Remove bogus reference to Emacs in project documentation :DOC:
- - State "DONE" [2008-07-16 Wed 03:59]
- The gnucash docs talk about there someday being an Emacs mode. There is
- already one.
- :PROPERTIES:
- :Submitter: bpt <#ledger>
- :Version: 2.4.1
- :Ticket: 10
- :ID: B81ADF25-F176-4ABC-9C2B-1090E4F2FA7D
- :END:
- [2007-12-10 Mon]
-* DONE [#C] Segfault with commodity price in budget.
- - State "DONE" [2008-07-17 Thu 20:09]
- :DATA:
-~ Monthly
- Assets:Invest 2 AAPL @ $30.00
- Assets:Bank -2 AAPL
- :END:
- It works if the '@ $30.00' is removed. The problem is that entry is null
- when called through parse_transactions. Backtrace:
- :OUTPUT:
-#0 0x080632ab in datetime_t (this=0xbfb4af88, _when=@0x40) at datetime.h:173
-#1 0x080973ac in ledger::entry_t::actual_date (this=0x0) at journal.h:180
-#2 0x080b7fc7 in ledger::parse_transaction (
- line=0x8119e20 " Assets:Invest 2 AAPL @ $30.00", account=0x813be00,
- entry=0x0) at textual.cc:258
-#3 0x080b9480 in ledger::parse_transactions (in=@0xbfb4b4bc,
- account=0x813be00, entry=@0x813e2f8, kind=@0xbfb4b2f8, beg_pos=63)
- at textual.cc:340
-...
- :END:
- :PROPERTIES:
- :Submitter: Nathan Jones <nathanj@insightbb.com>
- :Version: 2.6.0.90
- :Ticket: 191
- :ID: A4F87484-1B1D-4C76-B0AB-70E20FBA9D1B
- :END:
- [2008-04-23 Wed]
-* DONE [#B] Segmentation fault on import from GnuCash
- - State "DONE" [2008-07-17 Thu 20:04]
- - State "TODO" [2008-06-16 Mon 16:05] \\
- Luben Manolov <lubo@manolov.org> writes:
- > Import of this GnuCash file causes Segmentation fault
- I am trying to import a simple GnuCash file and I am getting "Segmentation
- fault" error. Please find attached the sample file.
- :OUTPUT:
-./ledger -f sample.gnucash balance
-While balancing entry:
- 2008/06/16
- Segmentation fault
- :END:
- :PROPERTIES:
- :Submitter: Luben Manolov <lubo@manolov.org>
- :Version: 2.6
- :Ticket: 198
- :ID: 266D96D2-DEB5-4BD9-A51B-B2F652E2F550
- :Attachments: sample.gnucash
- :END:
- [2008-06-16 Mon]
-* DONE [#B] Some at-signs are not properly escaped in documentation :DOC:
- - State "DONE" [2008-03-27 Thu 19:42]
- Some of the at signs are not properly escaped in the texi
- documentation. This leads to great confusion when trying to figure out how
- to use commodity transactions.
- :PROPERTIES:
- :Submitter: thedward <thedward@barsoom.net>
- :Version: 2.6
- :Ticket: 31
- :Attachments: ledger-texi.patch
- :ID: A7CA0F5B-1F08-417A-9071-A223601100CA
- :END:
- [2008-01-28 Mon]
-* DONE [#A] Strip \r from lines when parsing on Windows
- - State "DONE" [2008-07-17 Thu 18:31]
- It sounds like I'm not stripping the \r from the \r\n sequence, and thus
- it's interpreting the \r as part of the file name. I'll add this to the
- buglist for 3.0.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 43
- :ID: 458B2B74-AF2D-4D9D-89E4-D8AC26CFD531
- :END:
- [2008-04-05 Sat]
-* DONE [#A] trailing whitespace is significant in 2.6
- - State "DONE" [2008-04-05 Sat 18:56] \\
- The first patch fixes parsing account names when a single space follows.
- This might close ticket #3.
- - State "TODO" [2008-04-05 Sat 18:55] \\
- The following patch, submitted by Nathan Jones, proposes to fix this problem.
- - State "TODO" [2007-09-22 Sat 04:26] \\
- Simon, have you tried this with 2.6.1-svn? I believe this is something I
- fixed.
- Unlike 2.5, 2.6 considers an account name followed by whitespace to be
- different from one without (when no amount is specified).
- :PROPERTIES:
- :Submitter: Simon Michael <simon@joyful.com>
- :Version: 2.6
- :Ticket: 3
- :Attachments: 288.patch
- :ID: FB2330E1-AD78-4559-A885-A488DFDF3DC1
- :END:
- [2007-09-22 Sat]
-* DONE [#B] Unbalanced transactions due to rounding problems
- - State "DONE" [2008-09-17 Wed 05:03] \\
- The cents disappeared because 'D $1,000.00' must be specified at the beginning
- of the file, since you never use dollar figures outside of the pricing.
-
- The extra penny crept in because of the way that commodity have "lot" details
- automatically associated with them. I've now reduced this to the price only,
- since that's what most people are likely to use, just as this example does.
- - State "TODO" [2008-08-01 Fri 13:34] \\
- Levin <zslevin@gmail.com> writes:
- > This is the result of ledger in git master branch:
- :OUTPUT:
-./ledger -f test.ledger -V reg HLIT
-2008/06/01 BUY HLIT Assets:HLIT $750 $750
-2008/07/02 SELL HLIT Assets:HLIT $-658 0
- Assets:HLIT $658 $658
- Assets:HLIT $-658 0
- :END:
- > I wonder why .xxx is vanished :)
- I found some more rounding problems now that I've upgraded to 2.6.1. These
- transactions balanced in version 2.5.
- :DATA:
-2008/06/01 BUY HLIT
- Assets:HLIT 15 HLIT @ $50.00
- Assets
-
-2008/07/02 SELL HLIT
- Assets:HLIT -15 HLIT @ $50.00
- Assets:HLIT 15 HLIT @ $43.875
- Assets:HLIT -15 HLIT @ $43.875
- Assets
- :END:
- :OUTPUT:
-[20:30:53 vinod]:~/data $ ledger -V reg HLIT
-2008/06/01 BUY HLIT Assets:HLIT $750.00 $750.00
-2008/07/02 SELL HLIT Assets:HLIT $-658.12 $0.01
- Assets:HLIT $658.13 $658.14
- Assets:HLIT $-658.12 $0.01
- :END:
- So, I end up with an extra penny. I think it's because 658.125 rounds down
- on one entry and rounds up on the other.
- :PROPERTIES:
- :Submitter: Vinod Kurup <vvkurup@gmail.com>
- :Version: 2.6.1b
- :Ticket: 207
- :ID: E87DD3A5-B061-46A0-95E9-9844A6CB0443
- :END:
- [2008-08-01 Fri]
-* DONE [#C] When reporting the unbalanced remainder, round it :FEATURE:
- - State "DONE" [2008-07-17 Thu 20:52]
- This is so that it shows what ledger is really thinking.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 125
- :ID: 4BF95CDC-972F-4F39-9F54-7BEFD404F9AA
- :END:
- [2008-04-11 Fri]
-* WONTFIX [#C] Balance calculations using the '=' operator are off
- - State "WONTFIX" [2008-08-15 Fri 04:14] \\
- This feature is not ready for 2.6.1, and is being pushed to 3.0 where this
- issue has been fixed.
- When I run 'ledger --tail 20 reg assets:cash' with my current ledger data,
- the final balance is way, way off. Something is being miscalculated.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6.1b
- :Ticket: 209
- :ID: F32E914F-D485-427B-89E9-33C762CC1A47
- :END:
- [2008-08-02 Sat]
-* WONTFIX [#B] No commodity when amount contains simple math operation
- - State "WONTFIX" [2007-11-09 Fri 23:34] \\
- This expected behavior. If you multiply or divide two commoditized
- amounts together, the second commodity is dropped in favor of the first.
- You'll have to use "30 AAPL * .01".
- Use the following legder data file (sample2.dat)
- :DATA:
-2004/05/01 * Investment balance
- Assets:Brokerage 100 / 30 AAPL @ $30.00
- Equity:Opening Balances
- :END:
-
- Create the bal report:
- :OUTPUT:
-$ ledger -f sample2.dat bal
- 3.333333 Assets
- $-99.99999 Equity
---------------------
- 3.333333
- $-99.99999
- :END:
-
- Notice that the "AAPL" commodity is gone.
- :PROPERTIES:
- :Submitter: Levin <zslevin@gmail.com>
- :Version: 2.6
- :Ticket: 7
- :ID: 4290A2E5-8CFB-4529-87DE-F088719AF13A
- :END:
- [2007-11-09 Fri]
-* WONTFIX [#C] Non-balanced virtual transaction should fail.
- - State "WONTFIX" [2008-07-17 Thu 20:44] \\
- This is not an error because:
-
- 1. specifying no amount is the same as specifying an uncommoditized zero.
- 2. the second line will "auto-balance" with the first line.
- 3. the third line simply is a no-op, which I allow for the sake of script
- writers.
-
- There could be a warning for something like this, but then that's the
- danger of using () around an account name: you are explicitly stating you
- do not wish the transaction to be balanced.
- - State "TODO" [2008-04-23 Wed 13:35] \\
- Martin Blais <blais@furius.ca> writes:
- > Well... should "probably" fail. I mean, it does nothing, so it's
- > probably an error. I'd make it fail.
- Shouldn't this fail?
- :DATA:
-2004/03/25 Donations
- Assets:Checking $100.00
- Assets:Savings
- (Income:Donations)
- :END:
- :PROPERTIES:
- :Submitter: Martin Blais <blais@furius.ca>
- :Version: 2.6
- :Ticket: 190
- :ID: 75E83651-B130-4978-89C7-DFED4E874E8F
- :END:
- [2008-04-23 Wed]
-* WONTFIX [#B] Problem with pricing specification in prices.db file
- - State "WONTFIX" [2008-07-17 Thu 21:42] \\
- Pricing info is not used for balancing entries. For that, you'd need to use
- "@ ... USD" for the halfg and gouda amounts, so that Ledger could be certain
- your entries balances to zero.
- - State "TODO" [2008-04-05 Sat 20:09] \\
- I changed it to this below, and ledger stopped complaining:
- :DATA:
-2007/03/07 Irena
- Liabilities:Cash:Irena 7.00 USD
- Liabilities:Order1:Irena -1 gouda
-
-2007/03/07 Irena
- Liabilities:Cash:Irena 11.00 USD
- Liabilities:Order1:Irena -4 halfg
- :END:
- :OUTPUT:
-djw@hector:~$ ledger bal
-
-2007/03/07 Irena
- Liabilities:Cash:Irena 18.00 USD
- Liabilities:Order1:Irena -4 halfg
- Liabilities:Order1:Irena -1 gouda
-Error: /home/djw/milk.ledger, line 106: Entry above does not balance; remainder is: 18.00 USD
--1 gouda
--4 halfg
- :END:
- Here is what is in the prices.db file:
- :DATA:
-C 1.00 USD = $1.21
-P 2007/03/04 00:00:00 halfg 2.75 USD
-P 2007/03/04 00:00:00 gouda 7 USD
- :END:
- So you multiply 4*2.75 and add 7, you get 18. Since the units are USD, what
- is the beef? Why isn't ledger seeing 1 gouda and 4 halfg as 18 USD?
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 42
- :ID: 43CFF7FF-DA09-478C-AED1-2D2756BACA09
- :END:
- [2008-04-05 Sat]
-* WORKSFORME [#B] ledger -MA doesn't give a monthly report if some months have no transactions
- - State "WORKSFORME" [2008-07-17 Thu 20:14] \\
- This works for me.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 61
- :ID: FD118D79-3B8F-48CE-89D0-F0FFD46F6C49
- :END:
- [2008-04-11 Fri]
-* WORKSFORME [#C] ledger -Mn
- - State "WORKSFORME" [2008-08-17 Sun 20:13]
- Is not the same as: ledger -M -n
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 126
- :ID: 2C3B5DCE-AB7F-41A2-BF93-56CC1222AE64
- :END:
- [2008-04-11 Fri]
-* WORKSFORME [#A] Monthly register command displays nothing
- - State "WORKSFORME" [2008-07-17 Thu 20:12] \\
- This has apparently been fixed by the recent date/time bug fixes.
- The command is:
- :SCRIPT:
-ledger -p 2005 -e 2005/08/17 --monthly reg
- :END:
- This is against my own ledger file.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 30
- :ID: 841041A2-925D-4797-BE44-11BFC7333054
- :END:
- [2007-12-10 Mon]
-* WORKSFORME [#B] Problems with the prices.db file
- - State "WORKSFORME" [2008-07-17 Thu 21:45] \\
- Pricing entries must start with a capital P, not a lowercase p.
-
- This bug also mentions other issues, which are now contained in another
- bug.
- - State "TODO" [2008-04-05 Sat 20:06] \\
- However, even though I do not receive parse errors any longer, the
- price-db command does not work the way I expect it to. When I issue a
- 'bal' option, ledger still outputs the values in their commodity rather
- than the dollar amount, so even though I am not receiving an error, it
- still does not seem to work for me.
- My prices.db file looks like:
- :DATA:
-p 2007/01/14 02:18:01 WMCVX $5.04
-p 2007/01/14 02:18:02 WMICX $6.65
- :END:
- Notice there is no carriage return after the second line and that the file
- begins on line 1.
-
- When I run 'ledger --price-db prices.db bal' I get the following:
- :OUTPUT:
-Error: prices.db, line 2: Failed to parse dateP
-Error: Errors parsing file 'life/finances/ledger/prices.db'
- :END:
-
- If I have a carriage return on the second line, I get errors for both line 2
- and line 3. If i have one entry on a single line, I get an error for line 2.
-
- Any ideas?
-
- Also, I would like to get the prices.db perl script working to automatically
- grab the values from Fidelity, but I have not been able to do anything
- beyond installing the appropriate perl modules. If there are any
- instructions for this usage, I would appreciate it.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 40
- :ID: B8173D32-D7EB-4619-8488-B2C641431FDE
- :END:
- [2008-04-05 Sat]
-* WORKSFORME [#A] Weekly register report is completely broken in 2.6
- - State "WORKSFORME" [2008-07-17 Thu 20:11] \\
- This has apparently been fixed by all the other date/time fixes done today.
- The command is:
- :SCRIPT:
-ledger --weekly reg food
- :END:
- This works fine in 2.5.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 26
- :ID: 30383931-3060-4999-8FD3-9002E02366A0
- :END:
- [2007-12-10 Mon]
-* INVALID [#B] Remove bogus reference to Emacs in project documentation (2.6)
- - State "INVALID" [2008-07-13 Sun 22:16]
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 72
- :ID: 7455E4A7-16FD-4F41-8A33-CF44F6E690B2
- :END:
- [2008-04-11 Fri]
-* DUPLICATE [#A] Bug with date ranges
- - State "DUPLICATE" [2008-04-04 Fri 14:35] \\
- This has been fixed, see the comments in #36.
- I'm using the latest source from CVS and it appears the `-e` option is
- broken. For example this works as expected:
- :OUTPUT:
-% ledger -b 2006/05/01 bal
- :END:
-
-But this does not. No output whatsoever:
- :OUTPUT:
-% ledger -b 2006/05/01 -e 2006/05/31 bal
- :END:
-
-This also doesn't work. It just shows `Opening Balances: 0`:
- :OUTPUT:
-% ledger -p "last month" bal
- :END:
- :PROPERTIES:
- :Submitter: Eric Davis <edavis@insanum.com>
- :Version: 2.6
- :Ticket: 17
- :ID: FE3E08C0-802A-4FAA-B8BA-93D81C061148
- :END:
- [2007-12-10 Mon]
-* DUPLICATE [#A] DOS format line endings are fooling the parser
- - State "DUPLICATE" [2008-08-16 Sat 03:56] \\
- Duplicated by #43.
- The \r\n ending is having only the \n stripped, making the \r appear as part
- of the filename when doing a !include.
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 129
- :ID: 6DF2250F-C54D-4F67-AFB6-F8656020D394
- :END:
- [2008-04-11 Fri]
-* DUPLICATE [#C] Entry command produces duplicate source transactions
- - State "DUPLICATE" [2008-01-31 Thu 14:57] \\
- drewr writes:
- > This is a duplicate of ticket #8.
- - State "TODO" [2008-01-30 Wed 17:36] \\
- drewr writes:
- > This happens with 2.6.1 as well.
- If I have a ledger file like so:
- :DATA:
-2008/01/24 Foo
- Expenses:Foo $ 136.56
- Assets:Checking
- :END:
- and then run `ledger entry 2008/01/26 foo expen 45 check`, I get:
- :OUTPUT:
-2008/01/26 Foo
- Expenses:Foo $ 45.00
- Assets:Checking $ -136.56
- Assets:Checking $ 91.56
- :END:
- :Submitter: drewr <#ledger>
- :Version: 2.6
- :Ticket: 32
- :ID: EA246228-3EC7-4834-B55A-455DBA58116C
- :END:
- [2008-01-30 Wed]
-* DUPLICATE [#B] Need to strip \r from \r\n line endings
- - State "DUPLICATE" [2008-07-13 Sun 22:38]
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 139
- :ID: C7A61E89-08D1-4151-AF2E-92F666148F19
- :END:
- [2008-04-11 Fri]
-* DUPLICATE [#B] Problems parsing an entry
- - State "DUPLICATE" [2008-07-18 Fri 02:12]
- :OUTPUT:
-djw@hector:~$ ledger bal
-
-2007/03/07 Irena
-Liabilities:Cash:Irena 18.00 USD
-Liabilities:Order1:Irena -4 halfg
-Liabilities:Order1:Irena -1 gouda
-Error: /home/djw/milk.ledger, line 106: Entry above does not balance; remainder is: 18.00 USD
--1 gouda
--4 halfg
- :END:
- Here is what is in the prices.db file:
- :DATA:
-C 1.00 USD = $1.21
-P 2007/03/04 00:00:00 halfg 2.75 USD
-P 2007/03/04 00:00:00 gouda 7 USD
- :END:
- So you multiply 4*2.75 and add 7, you get 18. Since the units are USD, what
- is the beef? Why isn't ledger seeing 1 gouda and 4 halfg as 18 USD?
- :PROPERTIES:
- :Submitter: John Wiegley <johnw@newartisans.com>
- :Version: 2.6
- :Ticket: 133
- :ID: AD876FB0-E7B8-4C89-9E23-2D25AF8D5F0A
- :END:
- [2008-04-11 Fri]
-* DUPLICATE [#B] Reconciling doesn't work in ledger.el :EMACS:
- - State "DUPLICATE" [2008-07-16 Wed 03:56] \\
- Duplicated by #64.
- I've tried version 2.5 but have had some problems.
-
- I use Carbon Emacs on Mac OS X to edit my Ledger files. Unfortunately the
- reconcile functionality doesn't work any more. Pressing the space bar
- doesn't always toggle an entry, sometimes it needs to be pressed twice,
- sometimes it never goes. Additionally, even if some entries are toggled,
- nothing is changed in the main file and pressing C-c C-c just re-sets the
- reconcile window back to it's original state.
-
- I've tried with and without the new ledger-clear-whole-entries variable set.
- :PROPERTIES:
- :Submitter: Karen Cooke <karen.cooke@gmail.com>
- :Version: 2.6
- :Ticket: 14
- :ID: 2B02E2FD-DCF8-4CD8-A7FA-F83F5DAE3F55
- :END:
- [2007-12-10 Mon]
diff --git a/acprep b/acprep
index fe9034be..20be2db4 100755
--- a/acprep
+++ b/acprep
@@ -1,60 +1,1570 @@
-#!/bin/sh
-
-export AUTOCONF_VERSION=2.61
-export AUTOMAKE_VERSION=1.9
-
-sh ./autogen.sh
-
-HERE="$PWD"
-
-if [ "$1" = "--local" ]; then
- shift 1
-fi
-
-INCDIRS="-I/opt/local/include -I/usr/local/include -I/usr/include/httpd/xml"
-INCDIRS="$INCDIRS -I/opt/local/include/libofx"
-INCDIRS="$INCDIRS -I/usr/include/python2.5"
-LIBDIRS="-L/opt/local/lib -L/usr/local/lib"
-
-SYSTEM=`uname -s`
-
-if [ $SYSTEM = Linux ]; then
- CXXFLAGS="-pthread"
-elif [ $SYSTEM = Solaris ]; then
- CXXFLAGS="-pthreads"
-elif [ $SYSTEM = Darwin ]; then
- #CXXFLAGS="-arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk"
- CXXFLAGS="$CXXFLAGS -Wno-long-double"
- #LIBDIRS="$LIBDIRS -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk"
-else
- CXXFLAGS=""
-fi
-
-if [ "$1" = "--debug" ]; then
- shift 1
- $HERE/configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \
- CXXFLAGS="$CXXFLAGS -g" --enable-debug --enable-python "$@"
-elif [ "$1" = "--opt" ]; then
- shift 1
- $HERE/configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \
- CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -O3 -mcpu=7450 -fPIC" "$@"
-elif [ "$1" = "--flat-opt" ]; then
- shift 1
- $HERE/configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \
- CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -O3 -mcpu=7450" "$@"
-elif [ "$1" = "--safe-opt" ]; then
- shift 1
- $HERE/configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \
- CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -O3 -mcpu=7450 -fPIC -DDEBUG_LEVEL=1" "$@"
-elif [ "$1" = "--perf" ]; then
- shift 1
- $HERE/configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \
- CXXFLAGS="$CXXFLAGS -g -pg" "$@"
-elif [ "$1" = "--python" ]; then
- shift 1
- $HERE/configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \
- CXXFLAGS="$CXXFLAGS -g" --enable-python "$@"
-else
- $HERE/configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \
- CXXFLAGS="$CXXFLAGS -g" "$@"
-fi
+#!/usr/bin/env python
+
+# acprep, version 3.0
+#
+# This script configures my ledger source tree on my Mac OS/X machine. This
+# is not necessary, however, since I keep all the files necessary for building
+# checked in to the source tree. Users can just type './configure && make'.
+# This script simply sets up the compiler and linker flags for all the various
+# build permutations I use for testing and profiling.
+
+import inspect
+import logging
+import logging.handlers
+import optparse
+import os
+import re
+import shutil
+import string
+import sys
+import time
+import tempfile
+import datetime
+
+try:
+ import hashlib
+except:
+ import md5
+
+from os.path import *
+from stat import *
+from subprocess import Popen, PIPE, call
+
+LEVELS = {'DEBUG': logging.DEBUG,
+ 'INFO': logging.INFO,
+ 'WARNING': logging.WARNING,
+ 'ERROR': logging.ERROR,
+ 'CRITICAL': logging.CRITICAL}
+
+
+class CommandLineApp(object):
+ "Base class for building command line applications."
+
+ force_exit = True # If true, always ends run() with sys.exit()
+ log_handler = None
+ darwin_gcc = False
+
+ options = {
+ 'debug': False,
+ 'verbose': False,
+ 'logfile': False,
+ 'loglevel': False
+ }
+
+ def __init__(self):
+ "Initialize CommandLineApp."
+ # Create the logger
+ self.log = logging.getLogger(os.path.basename(sys.argv[0]))
+ ch = logging.StreamHandler()
+ formatter = logging.Formatter("%(name)s: %(levelname)s: %(message)s")
+ ch.setFormatter(formatter)
+ self.log.addHandler(ch)
+ self.log_handler = ch
+
+ # Setup the options parser
+ usage = 'usage: %prog [OPTIONS...] [ARGS...]'
+ op = self.option_parser = optparse.OptionParser(usage = usage,
+ conflict_handler = 'resolve')
+ op.add_option('', '--debug',
+ action='store_true', dest='debug',
+ default=False, help='show debug messages and pass exceptions')
+ op.add_option('-v', '--verbose',
+ action='store_true', dest='verbose',
+ default=False, help='show informational messages')
+ op.add_option('-q', '--quiet',
+ action='store_true', dest='quiet',
+ default=False, help='do not show log messages on console')
+ op.add_option('', '--log', metavar='FILE',
+ type='string', action='store', dest='logfile',
+ default=False, help='append logging data to FILE')
+ op.add_option('', '--loglevel', metavar='LEVEL',
+ type='string', action='store', dest='loglevel',
+ default=False, help='set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL')
+ return
+
+ def main(self, *args):
+ """Main body of your application.
+
+ This is the main portion of the app, and is run after all of the
+ arguments are processed. Override this method to implment the primary
+ processing section of your application."""
+ pass
+
+ def handleInterrupt(self):
+ """Called when the program is interrupted via Control-C or SIGINT.
+ Returns exit code."""
+ self.log.error('Canceled by user.')
+ return 1
+
+ def handleMainException(self):
+ "Invoked when there is an error in the main() method."
+ if not self.options.debug:
+ self.log.exception('Caught exception')
+ return 1
+
+ ## INTERNALS (Subclasses should not need to override these methods)
+
+ def run(self):
+ """Entry point.
+
+ Process options and execute callback functions as needed. This method
+ should not need to be overridden, if the main() method is defined."""
+ # Process the options supported and given
+ self.options, main_args = self.option_parser.parse_args()
+
+ if self.options.logfile:
+ fh = logging.handlers.RotatingFileHandler(self.options.logfile,
+ maxBytes = (1024 * 1024),
+ backupCount = 5)
+ formatter = logging.Formatter("%(asctime)s - %(levelname)s: %(message)s")
+ fh.setFormatter(formatter)
+ self.log.addHandler(fh)
+
+ if self.options.quiet:
+ self.log.removeHandler(self.log_handler)
+ ch = logging.handlers.SysLogHandler()
+ formatter = logging.Formatter("%(name)s: %(levelname)s: %(message)s")
+ ch.setFormatter(formatter)
+ self.log.addHandler(ch)
+ self.log_handler = ch
+
+ if self.options.loglevel:
+ self.log.setLevel(LEVELS[self.options.loglevel])
+ elif self.options.debug:
+ self.log.setLevel(logging.DEBUG)
+ elif self.options.verbose:
+ self.log.setLevel(logging.INFO)
+
+ exit_code = 0
+ try:
+ # We could just call main() and catch a TypeError, but that would
+ # not let us differentiate between application errors and a case
+ # where the user has not passed us enough arguments. So, we check
+ # the argument count ourself.
+ argspec = inspect.getargspec(self.main)
+ expected_arg_count = len(argspec[0]) - 1
+
+ if len(main_args) >= expected_arg_count:
+ exit_code = self.main(*main_args)
+ else:
+ self.log.debug('Incorrect argument count (expected %d, got %d)' %
+ (expected_arg_count, len(main_args)))
+ self.option_parser.print_help()
+ exit_code = 1
+
+ except KeyboardInterrupt:
+ exit_code = self.handleInterrupt()
+
+ except SystemExit, msg:
+ exit_code = msg.args[0]
+
+ except Exception:
+ exit_code = self.handleMainException()
+ if self.options.debug:
+ raise
+
+ if self.force_exit:
+ sys.exit(exit_code)
+ return exit_code
+
+
+class PrepareBuild(CommandLineApp):
+ #########################################################################
+ # Initialization routines #
+ #########################################################################
+
+ def initialize(self):
+ self.log.debug('Initializing all state variables')
+
+ self.should_clean = False
+ self.configured = False
+ self.current_ver = None
+ #self.current_flavor = 'default'
+ self.current_flavor = 'debug'
+ self.products_dir = None
+ self.build_dir = self.source_dir
+ self.configure_args = ['--with-included-gettext', '--enable-python']
+ self.sys_include_dirs = []
+ self.sys_library_dirs = []
+
+ self.CPPFLAGS = []
+ self.CFLAGS = []
+ self.CXXFLAGS = []
+ self.LDFLAGS = []
+
+ self.envvars = {
+ 'PYTHON_HOME': '/usr',
+ 'PYTHON_VERSION': '2.6',
+ 'BOOST_SUFFIX': None,
+ 'BOOST_HOME': '/usr',
+ 'LEDGER_PRODUCTS': None,
+ 'CC': 'gcc',
+ 'CPPFLAGS': '',
+ 'CFLAGS': '',
+ 'CXX': 'g++',
+ 'CXXFLAGS': '',
+ 'LD': 'g++',
+ 'LDFLAGS': ''
+ }
+
+ for varname in self.envvars.keys():
+ if os.environ.has_key(varname):
+ self.envvars[varname] = os.environ[varname]
+
+ if varname.endswith('FLAGS'):
+ self.__dict__[varname] = string.split(os.environ[varname])
+ self.envvars[varname] = ''
+
+ # If ~/Products/ or build/ exists, use them instead of the source tree
+ # for building
+ products = self.default_products_directory()
+ if (exists(products) and isdir(products)) or \
+ (exists('build') and isdir('build')):
+ self.build_dir = None
+
+ def __init__(self):
+ CommandLineApp.__init__(self)
+ self.log.setLevel(logging.INFO)
+
+ op = self.option_parser
+ op.add_option('-j', '--jobs', metavar='N',
+ type='int', action='store', dest='jobs',
+ default=1, help='Allow N make jobs at once')
+ op.add_option('', '--boost', metavar='SUFFIX',
+ action="callback", type="string",
+ callback=self.option_boost,
+ help='Set Boost library suffix (ex: "--boost=-mt")')
+ op.add_option('', '--force', action="callback",
+ callback=self.option_force,
+ help="Perform every action, without checking")
+ op.add_option('', '--glibcxx-debug', action='store_true',
+ dest='use_glibcxx_debug', default=False,
+ help='Define _GLIBCXX_DEBUG=1 during compilation')
+ op.add_option('', '--help', action="callback",
+ callback=self.option_help,
+ help='Show this help text')
+ op.add_option('', '--local', action="callback",
+ callback=self.option_local,
+ help='Build directly within the source tree (default)')
+ op.add_option('', '--no-pch', action="callback",
+ callback=self.option_no_pch,
+ help='Do not use pre-compiled headers')
+ op.add_option('', '--no-patch', action='store_true', dest='no_patch',
+ default=False,
+ help='Do not patch the Makefile for prettier output')
+ op.add_option('', '--no-git', action='store_true', dest='no_git',
+ default=False,
+ help='Do not call out to Git; useful for offline builds')
+ op.add_option('', '--output', metavar='DIR', action="callback",
+ callback=self.option_output,
+ help='Build in the specified directory')
+ op.add_option('', '--pch', action="callback",
+ callback=self.option_pch,
+ help='Enable use of pre-compiled headers')
+ op.add_option('', '--pic', action="callback",
+ callback=self.option_pic,
+ help='Compile with explicit PIC support')
+ op.add_option('', '--products', metavar='DIR', action="callback",
+ callback=self.option_products,
+ help='Collect all build products in this directory')
+ op.add_option('', '--trees', action="callback",
+ callback=self.option_trees,
+ help='Use separate build trees for each flavor')
+ op.add_option('', '--release', action="callback",
+ callback=self.option_release,
+ help='Setup for doing a faster, once-only build')
+ op.add_option('', '--warn', action="callback",
+ callback=self.option_warn,
+ help='Enable full warning flags')
+
+ self.force = False
+ self.no_pch = False
+ self.source_dir = os.getcwd()
+
+ self.initialize()
+
+ def main(self, *args):
+ if args and args[0] in ['default', 'debug', 'opt', 'gcov', 'gprof']:
+ self.current_flavor = args[0]
+ args = args[1:]
+
+ if args:
+ cmd = args[0]
+ if not PrepareBuild.__dict__.has_key('phase_' + cmd):
+ cmd = 'config'
+ else:
+ args = args[1:]
+ else:
+ cmd = 'config'
+
+ self.log.info('Invoking primary phase: ' + cmd)
+ PrepareBuild.__dict__['phase_' + cmd](self, *args)
+
+ #########################################################################
+ # General utility code #
+ #########################################################################
+
+ def execute(self, *args):
+ try:
+ self.log.debug('Executing command: ' + string.join(args, ' '))
+
+ retcode = call(args, shell=False)
+ if retcode < 0:
+ self.log.error("Child was terminated by signal", -retcode)
+ sys.exit(1)
+ elif retcode != 0:
+ self.log.error("Execution failed: " + string.join(args, ' '))
+ sys.exit(1)
+ except OSError, e:
+ self.log.error("Execution failed:", e)
+ sys.exit(1)
+
+ def get_stdout(self, *args):
+ try:
+ self.log.debug('Executing command: ' + string.join(args, ' '))
+
+ proc = Popen(args, shell=False, stdout=PIPE)
+ stdout = proc.stdout.read()
+ retcode = proc.wait()
+ if retcode < 0:
+ self.log.error("Child was terminated by signal",
+ -retcode)
+ sys.exit(1)
+ elif retcode != 0:
+ self.log.error("Execution failed: " + string.join(args, ' '))
+ sys.exit(1)
+ return stdout[:-1]
+ except OSError, e:
+ self.log.error("Execution failed:", e)
+ sys.exit(1)
+
+ def isnewer(self, file1, file2):
+ "Check if file1 is newer than file2."
+ if not exists(file2):
+ return True
+ return os.stat(file1)[ST_MTIME] > os.stat(file2)[ST_MTIME]
+
+ #########################################################################
+ # Determine information about the surroundings #
+ #########################################################################
+
+ def default_products_directory(self):
+ if self.envvars['LEDGER_PRODUCTS']:
+ return self.envvars['LEDGER_PRODUCTS']
+ else:
+ return join(os.environ['HOME'], "Products")
+
+ def products_directory(self):
+ if not self.products_dir:
+ products = self.default_products_directory()
+
+ if not exists(products) or not isdir(products):
+ products = join(self.source_dir, 'build')
+
+ products = join(products, basename(self.source_dir))
+
+ self.products_dir = products
+
+ return self.products_dir
+
+ def build_directory(self):
+ if not self.build_dir:
+ self.build_dir = join(self.products_directory(),
+ self.current_flavor)
+ return self.build_dir
+
+ def ensure(self, dirname):
+ if not exists(dirname):
+ self.log.info('Making directory: ' + dirname)
+ os.makedirs(dirname)
+ elif not isdir(dirname):
+ self.log.error('Directory is not a directory: ' + dirname)
+ sys.exit(1)
+ return dirname
+
+ def git_working_tree(self):
+ return exists('.git') and isdir('.git') and not self.options.no_git
+
+ def current_version(self):
+ if not self.current_ver:
+ if self.git_working_tree():
+ #date = self.get_stdout('git', 'log', '--format=%ci', '-1', 'HEAD')
+ #date = re.sub(" [-+][0-9][0-9][0-9][0-9]$", "", date)
+ #when = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
+ #self.current_ver = when.strftime("%Y%m%d_%H%M%S")
+ #commit = self.get_stdout('git', 'log', '--format=%h', 'HEAD^..HEAD')
+ #self.current_ver += "_" + commit
+ tag = self.get_stdout('git', 'describe', '--all', '--long')
+ self.current_ver = re.sub('heads/', '', tag)
+ else:
+ self.current_ver = "no-git"
+ return self.current_ver
+
+ def need_to_prepare_autotools(self):
+ if self.force:
+ return 'because it was forced'
+ elif self.isnewer('acprep', 'configure'):
+ self.should_clean = True
+ return 'because acprep is newer than configure'
+ elif self.isnewer('acprep', 'Makefile.in'):
+ self.should_clean = True
+ return 'because acprep is newer than Makefile.in'
+ elif self.isnewer('configure.ac', 'configure'):
+ return 'because confgure.ac is newer than configure'
+ elif self.isnewer('Makefile.am', 'Makefile.in'):
+ return 'because Makefile.am is newer than Makefile.in'
+ return False
+
+ def phase_products(self, *args):
+ self.log.info('Executing phase: products')
+ print self.products_directory()
+
+ def phase_info(self, *args):
+ self.log.info('Executing phase: info')
+
+ environ, conf_args = self.configure_environment()
+
+ self.log.info("Current version => " + self.current_version())
+ self.log.info("Current flavor => " + self.current_flavor)
+ self.log.info("Source directory => " + self.source_dir)
+ self.log.info("Need to run autogen.sh => " +
+ str(self.need_to_prepare_autotools()))
+ self.log.info("Products directory => " + self.products_directory())
+ self.log.info("Build directory => " + self.build_directory())
+ self.log.info("Need to run configure => " +
+ str(self.need_to_run_configure()))
+ self.log.info("Use _GLIBCXX_DEBUG => " +
+ str(self.options.use_glibcxx_debug))
+ self.log.info("Use pre-compiled headers => " +
+ str('--enable-pch' in conf_args))
+
+ self.log.debug('Configure environment =>')
+
+ keys = environ.keys()
+ keys.sort()
+ for key in keys:
+ if key in ['PATH', 'CC', 'LD', 'CXX'] or \
+ key.endswith('FLAGS'):
+ self.log.debug(' %s=%s' % (key, environ[key]))
+
+ self.log.debug('Configure arguments =>')
+
+ for arg in conf_args + list(args):
+ self.log.debug(' %s' % arg)
+
+ def phase_sloc(self, *args):
+ self.log.info('Executing phase: sloc')
+ self.execute('sloccount', 'src', 'python', 'lisp', 'test')
+
+ #########################################################################
+ # Configure source tree using autogen #
+ #########################################################################
+
+ def phase_gettext(self, *args):
+ self.log.info('Executing phase: gettext')
+
+ # configure the template files
+ assert exists('po') and isdir('po')
+ if not exists(join('po', 'Makevars')):
+ assert exists(join('po', 'Makevars.template'))
+ self.log.info('Moving po/Makevars.template -> po/Makevars')
+ os.rename(join('po', 'Makevars.template'),
+ join('po', 'Makevars'))
+
+ POTFILES_in = open('po/POTFILES.in', 'w')
+ for filename in (f for f in os.listdir(join(self.source_dir, 'src'))
+ if re.search('\.(cc|h)', f)):
+ POTFILES_in.write(join('src', filename))
+ POTFILES_in.write('\n')
+ POTFILES_in.close()
+
+ def phase_version(self, *args):
+ self.log.info('Executing phase: version')
+ version_m4 = open('version.m4', 'w')
+ version_m4.write("m4_define([VERSION_NUMBER], [%s])\n" %
+ self.current_version())
+ version_m4.close()
+
+ def phase_autogen(self, *args):
+ self.log.info('Executing phase: autogen')
+
+ if not exists('autogen.sh') or \
+ self.isnewer('tools/autogen.sh', 'autogen.sh'):
+ shutil.copyfile('tools/autogen.sh', 'autogen.sh')
+
+ self.execute('sh', 'tools/autogen.sh')
+
+ def phase_aclocal(self, *args):
+ self.log.info('Executing phase: aclocal')
+ self.execute('aclocal', '-I', 'm4')
+
+ def phase_autoconf(self, *args):
+ self.log.info('Executing phase: autoconf')
+
+ if not exists('configure.ac') or \
+ self.isnewer('tools/configure.ac', 'configure.ac'):
+ shutil.copyfile('tools/configure.ac', 'configure.ac')
+
+ if not exists('Makefile.am') or \
+ self.isnewer('tools/Makefile.am', 'Makefile.am'):
+ shutil.copyfile('tools/Makefile.am', 'Makefile.am')
+
+ reason = self.need_to_prepare_autotools()
+ if reason:
+ self.log.info('autogen.sh must be run ' + reason)
+ self.phase_version()
+ self.phase_autogen()
+ self.phase_gettext()
+ self.phase_aclocal()
+ else:
+ self.log.debug('autogen.sh does not need to be run')
+
+ #########################################################################
+ # Update local files with the latest information #
+ #########################################################################
+
+ def phase_submodule(self, *args):
+ self.log.info('Executing phase: submodule')
+ if self.git_working_tree():
+ self.execute('git', 'submodule', 'init')
+ self.execute('git', 'submodule', 'update')
+
+ def phase_pull(self, *args):
+ self.log.info('Executing phase: pull')
+ if self.git_working_tree():
+ self.execute('git', 'pull')
+ self.phase_submodule()
+
+ #########################################################################
+ # Automatic installation of build dependencies #
+ #########################################################################
+
+ def phase_dependencies(self, *args):
+ self.log.info('Executing phase: dependencies')
+
+ self.log.info("Installing Ledger's build dependencies ...")
+
+ system = self.get_stdout('uname', '-s')
+
+ if system == 'Darwin':
+ if exists('/opt/local/bin/port'):
+ self.log.info('Looks like you are using MacPorts on OS X')
+ packages = [
+ 'sudo', 'port', 'install', '-f',
+ 'automake',
+ 'autoconf',
+ 'libtool',
+ 'python26', '+universal',
+ 'libiconv', '+universal',
+ 'zlib', '+universal',
+ 'gmp' ,'+universal',
+ 'mpfr', '+universal',
+ 'ncurses', '+universal',
+ 'ncursesw', '+universal',
+ 'gettext' ,'+universal',
+ 'libedit' ,'+universal',
+ 'boost-jam',
+ 'boost', '+icu+python26+st+universal',
+ 'cppunit', '+universal',
+ #'texlive',
+ #'doxygen',
+ #'graphviz',
+ 'texinfo',
+ 'lcov',
+ 'sloccount'
+ ]
+ self.log.info('Executing: ' + string.join(packages, ' '))
+ self.execute(*packages)
+ elif exists('/sw/bin/fink'):
+ self.log.info('Looks like you are using Fink on OS X')
+ self.log.error("I don't know the package names for Fink yet!")
+
+ elif system == 'Linux':
+ if exists('/etc/issue'):
+ issue = open('/etc/issue')
+ if issue.readline().startswith('Ubuntu'):
+ release = open('/etc/lsb-release')
+ info = release.read()
+ release.close()
+ if re.search('karmic', info):
+ self.log.info('Looks like you are using APT on Ubuntu Karmic')
+ packages = [
+ 'sudo', 'apt-get', 'install',
+ 'build-essential',
+ 'libtool',
+ 'autoconf',
+ 'automake',
+ 'zlib1g-dev',
+ 'libbz2-dev',
+ 'python-dev',
+ 'libgmp3-dev',
+ 'libmpfr-dev',
+ 'bjam',
+ 'gettext',
+ 'cvs',
+ 'libboost1.40-dev',
+ 'libboost-regex1.40-dev',
+ 'libboost-date-time1.40-dev',
+ 'libboost-filesystem1.40-dev',
+ 'libboost-python1.40-dev',
+ 'libedit-dev',
+ 'libcppunit-dev',
+ #'texlive-full',
+ #'doxygen',
+ #'graphviz',
+ 'texinfo',
+ 'lcov',
+ 'sloccount'
+ ]
+ else:
+ self.log.info('Looks like you are using APT on Ubuntu Hardy')
+ packages = [
+ 'sudo', 'apt-get', 'install',
+ 'build-essential',
+ 'libtool',
+ 'autoconf',
+ 'automake',
+ 'zlib1g-dev',
+ 'libbz2-dev',
+ 'python-dev',
+ 'bjam',
+ 'cvs',
+ 'gettext',
+ 'libgmp3-dev',
+ 'libmpfr-dev',
+ 'libboost1.35-dev',
+ 'libboost-python1.35-dev',
+ 'libboost-regex1.35-dev',
+ 'libboost-date-time1.35-dev',
+ 'libboost-filesystem1.35-dev',
+ 'libedit-dev',
+ 'libcppunit-dev',
+ #'texlive-full',
+ #'doxygen',
+ #'graphviz',
+ 'texinfo',
+ 'lcov',
+ 'sloccount'
+ ]
+ self.log.info('Executing: ' + string.join(packages, ' '))
+ self.execute(*packages)
+
+ if exists('/etc/redhat-release'):
+ release = open('/etc/redhat-release')
+ if release.readline().startswith('CentOS'):
+ self.log.info('Looks like you are using YUM on CentOS')
+ packages = [
+ 'sudo', 'yum', 'install',
+ 'gcc',
+ 'gcc-c++',
+ 'compat-gcc-*',
+ 'make',
+ 'libtool',
+ 'autoconf',
+ 'automake',
+ 'zlib-devel',
+ 'bzip2-devel',
+ 'python-devel',
+ 'bboost-devel',
+ 'gmp-devel',
+ 'gettext-devel',
+ #'mpfr-devel'
+ 'libedit-devel',
+ 'cppunit-devel',
+ #'texlive-full',
+ #'doxygen',
+ #'graphviz',
+ 'texinfo',
+ #'lcov',
+ #'sloccount'
+ ]
+ self.log.info('Executing: ' + string.join(packages, ' '))
+ self.execute(*packages)
+
+ def phase_buildlibs(self, *args):
+ self.log.info('Executing phase: buildlibs')
+
+ try:
+ os.chdir('lib')
+
+ environ, conf_args = self.configure_environment()
+
+ boost = 'boost_1_41_0'
+ tarball = boost + '.7z'
+
+ if not exists(boost):
+ if not exists(tarball):
+ self.log.info('Downloading Boost source tarball ...')
+ self.execute('curl', '-L', '-o', tarball,
+ 'http://downloads.sourceforge.net/boost/' +
+ boost + '.7z?use_mirror=ufpr')
+
+ if not exists(tarball):
+ self.log.error('Failed to locate the Boost source tarball')
+ sys.exit(1)
+
+ fd = open(tarball)
+ try:
+ csum = hashlib.md5()
+ except:
+ csum = md5.md5()
+ csum.update(fd.read())
+ fd.close()
+ digest = csum.hexdigest()
+
+ if digest != 'b74ee2f0f46cef601544dd4ac2d7dec4':
+ self.log.error('Boost source tarball fails to match checksum')
+ sys.exit(1)
+
+ self.log.info('Extracting Boost source tarball ...')
+ self.execute('7za', 'x', tarball)
+
+ if not exists(boost):
+ self.log.error('Failed to locate the Boost sources')
+ sys.exit(1)
+
+ if not exists('cppunit') and self.git_working_tree():
+ self.execute('git', 'clone', 'git://github.com/jwiegley/cppunit.git')
+
+ if not exists('cppunit'):
+ self.log.error('Failed to locate the CppUnit sources')
+ sys.exit(1)
+
+ self.execute('make',
+ 'BOOST_SOURCE=%s' % boost,
+ 'CC=%s' % environ['CC'],
+ 'CXX=%s' % environ['CXX'],
+ 'LD=%s' % environ['LD'],
+ 'build-all')
+ finally:
+ os.chdir(self.source_dir)
+
+ #########################################################################
+ # Determine the system's basic configuration #
+ #########################################################################
+
+ def locate_boost_in_dir(self, path):
+ if exists(path) and isdir(path):
+ entries = os.listdir(path)
+ entries.sort()
+ for entry in entries:
+ if re.search('boost_regex', entry):
+ self.log.info('Found a Boost library: ' + entry)
+
+ match = re.match('libboost_regex([^.]*)\.(a|so|dylib)', entry)
+ if match:
+ suffix = match.group(1)
+ self.log.info('Found Boost suffix => ' + suffix)
+ self.envvars['BOOST_HOME'] = dirname(path)
+ return suffix
+ else:
+ self.log.debug('The directory "%s" is not valid, skipping' %
+ path)
+ return None
+
+ def inform_boost_location(self, text, suffix):
+ self.log.info('Boost %s here:' % text)
+ self.log.info('BOOST_HOME => ' + self.envvars['BOOST_HOME'])
+ self.log.info('BOOST_SUFFIX => ' + suffix)
+
+ def locate_boost(self):
+ if self.envvars['BOOST_SUFFIX']:
+ self.log.info(("Not looking for Boost, since " +
+ "a suffix of '%s' was given") %
+ self.envvars['BOOST_SUFFIX'])
+ else:
+ suffix = None
+ for path in ['/usr/local/lib', '/opt/local/lib',
+ '/sw/lib', '/usr/lib']:
+ self.log.info('Looking for Boost in %s...' % path)
+ suffix = self.locate_boost_in_dir(path)
+ if suffix is not None:
+ self.inform_boost_location('was found', suffix)
+ break
+ if suffix is None:
+ self.log.error("Boost could not be found.")
+ self.envvars['BOOST_SUFFIX'] = suffix
+ return self.envvars['BOOST_SUFFIX']
+
+ def setup_system_directories(self):
+ boost_suffix = self.locate_boost()
+
+ # Each of these becomes '-isystem <name>'
+ for path in ['/usr/local/include',
+ '%s/include/boost' %
+ self.envvars['BOOST_HOME'],
+ '%s/include' % self.envvars['BOOST_HOME'],
+ '%s/include/python%s' %
+ (self.envvars['PYTHON_HOME'],
+ self.envvars['PYTHON_VERSION'].strip()),
+ '/opt/local/include',
+ '/sw/include']:
+ if exists(path) and isdir(path) and \
+ path != '/usr/include':
+ self.log.info('Noticing include directory => ' + path)
+ self.sys_include_dirs.append(path)
+
+ # Each of these becomes '-L<name>'
+ for path in ['/usr/local/lib',
+ '%s/lib' % self.envvars['PYTHON_HOME'],
+ '%s/lib/python%s/config'
+ % (self.envvars['PYTHON_HOME'],
+ self.envvars['PYTHON_VERSION'].strip()),
+ '/opt/local/lib',
+ '/sw/lib']:
+ if exists(path) and isdir(path):
+ self.log.info('Noticing library directory => ' + path)
+ self.sys_library_dirs.append(path)
+
+ def setup_for_johnw(self):
+ if self.current_flavor == 'debug' or self.current_flavor == 'gcov':
+ if exists('/usr/local/stow/cppunit/include'):
+ self.sys_include_dirs.insert(0, '/usr/local/stow/cppunit/include')
+ self.sys_library_dirs.insert(0, '/usr/local/stow/cppunit/lib')
+
+ if exists('/usr/local/stow/icu/include'):
+ self.sys_include_dirs.insert(0, '/usr/local/stow/icu/include')
+ self.sys_library_dirs.insert(0, '/usr/local/stow/icu/lib')
+
+ self.CPPFLAGS.append('-D_GLIBCXX_FULLY_DYNAMIC_STRING=1')
+ self.configure_args.append('--disable-shared')
+
+ self.options.use_glibcxx_debug = True
+ else:
+ self.CXXFLAGS.append('-march=nocona')
+ self.CXXFLAGS.append('-msse3')
+
+ self.configure_args.append('--enable-doxygen')
+ self.configure_args.append('--enable-python')
+
+ def setup_for_system(self):
+ self.setup_system_directories()
+
+ system = self.get_stdout('uname', '-s')
+
+ self.log.info('System type is => ' + system)
+
+ # These options are global defaults at the moment
+ #self.option_warn()
+ if not self.no_pch:
+ self.option_pch()
+
+ if system == 'Linux':
+ arch = self.get_stdout('uname', '-m')
+ if arch == 'x86_64':
+ if '--disable-shared' in self.configure_args:
+ self.configure_args.remove('--disable-shared')
+ self.configure_args.append('--disable-static')
+ self.CXXFLAGS.append('-pthread')
+
+ elif system == 'Solaris':
+ self.CXXFLAGS.append('-pthread')
+
+ elif system == 'Darwin':
+ if exists('/Users/johnw/Dropbox/Accounts/ledger.dat'):
+ self.setup_for_johnw()
+
+ self.locate_darwin_libraries()
+
+ if (self.current_flavor == 'opt' or \
+ self.current_flavor == 'default') and \
+ exists('/usr/bin/g++-4.2'):
+ self.envvars['CC'] = '/usr/bin/gcc-4.2'
+ self.envvars['CXX'] = '/usr/bin/g++-4.2'
+ self.envvars['LD'] = '/usr/bin/g++-4.2'
+ self.darwin_gcc = True
+ elif exists('/opt/local/bin/g++-mp-4.4'):
+ self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.4'
+ self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.4'
+ self.envvars['LD'] = '/opt/local/bin/g++-mp-4.4'
+ elif exists('/opt/local/bin/g++-mp-4.3'):
+ self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.3'
+ self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.3'
+ self.envvars['LD'] = '/opt/local/bin/g++-mp-4.3'
+ elif exists('/usr/bin/g++-4.2'):
+ self.envvars['CC'] = '/usr/bin/gcc-4.2'
+ self.envvars['CXX'] = '/usr/bin/g++-4.2'
+ self.envvars['LD'] = '/usr/bin/g++-4.2'
+ self.darwin_gcc = True
+ else:
+ # g++ 4.0.1 cannot use PCH headers on OS X 10.5
+ self.option_no_pch()
+
+ if '--enable-pch' not in self.configure_args and \
+ (exists('/opt/local/bin/ccache') or \
+ exists('/usr/local/bin/ccache')):
+ self.envvars['CC'] = 'ccache ' + self.envvars['CC']
+ self.envvars['CXX'] = 'ccache ' + self.envvars['CXX']
+ self.envvars['LD'] = 'ccache ' + self.envvars['LD']
+
+ def setup_flags(self):
+ for path in self.sys_include_dirs:
+ self.CPPFLAGS.append('-isystem')
+ self.CPPFLAGS.append(path)
+
+ self.CXXFLAGS.append('-pipe')
+
+ for path in self.sys_library_dirs:
+ self.LDFLAGS.append('-L' + path)
+
+ def setup_flavor(self):
+ self.setup_for_system()
+
+ if not PrepareBuild.__dict__.has_key('setup_flavor_' +
+ self.current_flavor):
+ self.log.error('Unknown build flavor "%s"' % self.current_flavor)
+ sys.exit(1)
+
+ self.log.info('Setting up build flavor => ' + self.current_flavor)
+ PrepareBuild.__dict__['setup_flavor_' + self.current_flavor](self)
+
+ self.setup_flags()
+
+ def escape_string(self, data):
+ return re.sub('(["\\\\])', '\\\\\\1', data)
+
+ def finalize_config(self):
+ self.setup_flavor()
+
+ for var in ('CPPFLAGS', 'CFLAGS', 'CXXFLAGS', 'LDFLAGS'):
+ value = self.__dict__[var]
+ if value:
+ first = not self.envvars[var]
+ for member in value:
+ #escaped = self.escape_string(member)
+ #if member != escaped:
+ # member = escaped
+ if first:
+ first = False
+ else:
+ self.envvars[var] += ' '
+ self.envvars[var] += member
+ self.log.debug('Final value of %s: %s' %
+ (var, self.envvars[var]))
+
+ elif self.envvars.has_key(var):
+ del self.envvars[var]
+
+ #########################################################################
+ # Options that can modify any build flavor #
+ #########################################################################
+
+ def option_pch(self, option=None, opt_str=None, value=None, parser=None):
+ self.log.debug('Saw option --pch')
+
+ self.configure_args.append('--enable-pch')
+
+ self.CXXFLAGS.append('-fpch-deps')
+ self.CXXFLAGS.append('-Wconversion')
+ #self.CXXFLAGS.append('-Wold-style-cast')
+
+ system = self.get_stdout('uname', '-s')
+
+ def option_no_pch(self, option=None, opt_str=None, value=None, parser=None):
+ self.log.debug('Saw option --no-pch')
+
+ self.no_pch = True
+
+ if '--enable-pch' in self.configure_args:
+ self.configure_args.remove('--enable-pch')
+
+ if '-Wconversion' in self.configure_args:
+ self.CXXFLAGS.remove('-Wconversion')
+ #if '-Wold-style-cast' in self.configure_args:
+ # self.CXXFLAGS.remove('-Wold-style-cast')
+
+ system = self.get_stdout('uname', '-s')
+
+ if system == "Darwin":
+ self.envvars['CC'] = 'gcc'
+ self.envvars['CXX'] = 'g++'
+ self.envvars['LD'] = 'g++'
+
+ def option_force(self, option=None, opt_str=None, value=None, parser=None):
+ self.log.debug('Saw option --force')
+ self.force = True
+
+ def option_warn(self, option=None, opt_str=None, value=None, parser=None):
+ self.log.debug('Saw option --warn')
+ self.CXXFLAGS.append('-ansi')
+ self.CXXFLAGS.append('-pedantic')
+ self.CXXFLAGS.append('-pedantic-errors')
+ self.CXXFLAGS.append('-Wall')
+ self.CXXFLAGS.append('-Winvalid-pch')
+ self.CXXFLAGS.append('-Wextra')
+ self.CXXFLAGS.append('-Wcast-align')
+ self.CXXFLAGS.append('-Wcast-qual')
+ self.CXXFLAGS.append('-Wfloat-equal')
+ self.CXXFLAGS.append('-Wmissing-field-initializers')
+ self.CXXFLAGS.append('-Wno-endif-labels')
+ self.CXXFLAGS.append('-Woverloaded-virtual')
+ self.CXXFLAGS.append('-Wsign-compare')
+ self.CXXFLAGS.append('-Wsign-promo')
+ self.CXXFLAGS.append('-Wstrict-null-sentinel')
+ self.CXXFLAGS.append('-Wwrite-strings')
+ self.CXXFLAGS.append('-Wno-old-style-cast')
+ self.CXXFLAGS.append('-Wno-deprecated')
+ self.CXXFLAGS.append('-Wno-strict-aliasing')
+ self.CXXFLAGS.append('-Werror')
+
+ def option_boost(self, option=None, opt_str=None, value=None, parser=None):
+ self.log.debug('Saw option --boost')
+ self.envvars['BOOST_SUFFIX'] = value
+
+ def option_pic(self, option=None, opt_str=None, value=None, parser=None):
+ self.log.debug('Saw option --pic')
+ self.CXXFLAGS.append('-fPIC')
+
+ def option_output(self, option=None, opt_str=None, value=None, parser=None):
+ self.log.debug('Saw option --output')
+ self.build_dir = value
+
+ def option_products(self, option=None, opt_str=None, value=None, parser=None):
+ self.log.debug('Saw option --products')
+ self.products_dir = value
+
+ def option_local(self, option=None, opt_str=None, value=None, parser=None):
+ self.log.debug('Saw option --local')
+ self.build_dir = self.source_dir
+
+ def option_trees(self, option=None, opt_str=None, value=None, parser=None):
+ self.log.debug('Saw option --trees')
+ self.build_dir = None
+
+ def option_release(self, option=None, opt_str=None, value=None, parser=None):
+ self.log.debug('Saw option --release')
+ if '--disable-shared' in self.configure_args:
+ self.configure_args.remove('--disable-shared')
+ self.configure_args.append('--disable-dependency-tracking')
+
+ def option_help(self, option=None, opt_str=None, value=None, parser=None):
+ self.phase_help()
+
+ #########################################################################
+ # The various build flavors #
+ #########################################################################
+
+ def locate_darwin_libraries(self):
+ if self.current_flavor == 'debug' or self.current_flavor == 'gcov':
+ self.log.debug('We are using GLIBCXX_DEBUG, so setting up flags')
+
+ if self.options.use_glibcxx_debug:
+ self.CPPFLAGS.append('-D_GLIBCXX_DEBUG=1')
+
+ if exists('/usr/local/lib/libboost_regex-xgcc44-sd-1_41.a'):
+ self.envvars['BOOST_HOME'] = '/usr/local'
+ self.envvars['BOOST_SUFFIX'] = '-xgcc44-sd-1_41'
+ self.sys_include_dirs.append('/usr/local/include/boost-1_41')
+ self.inform_boost_location('is really located',
+ self.envvars['BOOST_SUFFIX'])
+
+ elif exists('/usr/local/lib/libboost_regex-xgcc44-d-1_41.a'):
+ self.envvars['BOOST_HOME'] = '/usr/local'
+ self.envvars['BOOST_SUFFIX'] = '-xgcc44-d-1_41'
+ self.sys_include_dirs.append('/usr/local/include/boost-1_41')
+ self.inform_boost_location('is really located',
+ self.envvars['BOOST_SUFFIX'])
+
+ elif exists('/opt/local/lib/libboost_regex-d.a'):
+ self.envvars['BOOST_HOME'] = '/opt/local'
+ self.envvars['BOOST_SUFFIX'] = '-d'
+ self.sys_include_dirs.append('/opt/local/include/boost')
+ self.inform_boost_location('is really located',
+ self.envvars['BOOST_SUFFIX'])
+
+ else:
+ if exists('/opt/local/lib/libboost_regex.a'):
+ self.envvars['BOOST_HOME'] = '/opt/local'
+ self.envvars['BOOST_SUFFIX'] = ''
+ self.sys_include_dirs.append('/opt/local/include/boost')
+ self.inform_boost_location('is really located',
+ self.envvars['BOOST_SUFFIX'])
+
+ elif exists('/usr/local/lib/libboost_regex-xgcc44-s-1_41.a'):
+ self.envvars['BOOST_HOME'] = '/usr/local'
+ self.envvars['BOOST_SUFFIX'] = '-xgcc44-s-1_41'
+ self.sys_include_dirs.append('/usr/local/include/boost-1_41')
+ self.inform_boost_location('is really located',
+ self.envvars['BOOST_SUFFIX'])
+
+ elif exists('/usr/local/lib/libboost_regex-xgcc44-1_41.a'):
+ self.envvars['BOOST_HOME'] = '/usr/local'
+ self.envvars['BOOST_SUFFIX'] = '-xgcc44-1_41'
+ self.sys_include_dirs.append('/usr/local/include/boost-1_41')
+ self.inform_boost_location('is really located',
+ self.envvars['BOOST_SUFFIX'])
+
+ def setup_flavor_default(self):
+ pass
+
+ def setup_flavor_debug(self):
+ self.configure_args.append('--enable-debug')
+
+ self.CXXFLAGS.append('-g')
+ self.LDFLAGS.append('-g')
+
+ def setup_flavor_opt(self):
+ if self.darwin_gcc:
+ self.option_no_pch()
+ if '--disable-shared' in self.configure_args:
+ self.configure_args.remove('--disable-shared')
+ self.configure_args.append('--disable-dependency-tracking')
+ for i in ['-fast']:
+ self.CXXFLAGS.append(i)
+ self.CFLAGS.append(i)
+ self.LDFLAGS.append(i)
+ for i in ['-arch', 'i386', '-arch', 'x86_64']:
+ self.CXXFLAGS.append(i)
+ self.CFLAGS.append(i)
+ self.LDFLAGS.append(i)
+ else:
+ for i in ['-O3', '-fomit-frame-pointer']:
+ self.CXXFLAGS.append(i)
+ self.CFLAGS.append(i)
+ self.LDFLAGS.append(i)
+
+ def setup_flavor_gcov(self):
+ self.CXXFLAGS.append('-g')
+ self.CXXFLAGS.append('-fprofile-arcs')
+ self.CXXFLAGS.append('-ftest-coverage')
+ self.LDFLAGS.append('-g')
+
+ def setup_flavor_gprof(self):
+ self.CXXFLAGS.append('-g')
+ self.CXXFLAGS.append('-pg')
+ self.LDFLAGS.append('-g')
+ self.LDFLAGS.append('-pg')
+
+ #########################################################################
+ # Prettify the output from automake, by rewriting the Makefile #
+ #########################################################################
+
+ def phase_patch(self, *args):
+ """Alter the Makefile so that it's not nearly so verbose.
+
+ This makes errors and warnings much easier to spot."""
+ self.log.info('Executing phase: patch')
+
+ if exists('Makefile'):
+ self.log.debug('Patching generated Makefile')
+ Makefile = open('Makefile')
+ Makefile_new = open('Makefile.new', 'w')
+ for line in Makefile.readlines():
+ line = re.sub('^\t(\$\((LIBTOOL|CXX)\).*?\.(cc|cpp))$',
+ '\t@echo " " CXX \$@;\\1 > /dev/null', line)
+ line = re.sub('^\tmv -f', '\t@mv -f', line)
+ line = re.sub('^\t\$\(am__mv\)', '\t@$(am__mv)', line)
+ line = re.sub('^\t(\$\((.*?)LINK\).*)',
+ '\t@echo " LD " \$@;\\1 > /dev/null', line)
+ Makefile_new.write(line)
+ Makefile_new.close()
+ Makefile.close()
+
+ os.remove('Makefile')
+ os.rename('Makefile.new', 'Makefile')
+
+ stamp = open('.timestamp', 'w')
+ stamp.write('timestamp')
+ stamp.close()
+
+ #########################################################################
+ # Configure build tree using autoconf #
+ #########################################################################
+
+ def configure_environment(self):
+ self.finalize_config()
+
+ environ = dict(os.environ)
+ for key, value in self.envvars.items():
+ if value:
+ environ[key] = value
+
+ environ['PATH'] = ('%s/bin:%s' %
+ (environ['PYTHON_HOME'], environ['PATH']))
+
+ if self.build_directory() == self.source_dir:
+ conf_args = ['sh', 'configure']
+ else:
+ conf_args = ['sh', join(self.source_dir, 'configure'),
+ '--srcdir', self.source_dir]
+
+ for var in ('CC', 'CPPFLAGS', 'CFLAGS', 'CXX', 'CXXFLAGS',
+ 'LD', 'LDFLAGS'):
+ if self.envvars.has_key(var) and self.envvars[var] and \
+ (var.endswith('FLAGS') or exists(self.envvars[var])):
+ conf_args.append('%s=%s' % (var, self.envvars[var]))
+
+ if environ.has_key('BOOST_SUFFIX') and environ['BOOST_SUFFIX']:
+ conf_args.append('--with-boost-suffix=%s' %
+ environ['BOOST_SUFFIX'])
+
+ return (environ, conf_args + self.configure_args)
+
+ def need_to_run_configure(self):
+ Makefile = join(self.build_directory(), 'Makefile')
+ if self.force:
+ return 'because it was forced'
+ elif not exists(Makefile):
+ return 'because Makefile does not exist'
+ elif self.isnewer(join(self.source_dir, 'configure'), Makefile):
+ return 'because configure is newer than Makefile'
+ elif self.isnewer(join(self.source_dir, 'Makefile.in'), Makefile):
+ return 'because Makefile.in is newer than Makefile'
+ return False
+
+ def phase_configure(self, *args):
+ self.log.info('Executing phase: configure')
+
+ self.configured = True
+
+ build_dir = self.ensure(self.build_directory())
+ try:
+ os.chdir(build_dir)
+
+ reason = self.need_to_run_configure()
+ if reason:
+ self.log.info('./configure must be run ' + reason)
+ self.log.debug('Source => ' + self.source_dir)
+ self.log.debug('Build => ' + build_dir)
+
+ environ, conf_args = self.configure_environment()
+ for arg in args:
+ if arg: conf_args.append(arg)
+
+ self.log.debug('configure env => ' + str(environ))
+ self.log.debug('configure args => ' + str(conf_args))
+
+ configure = Popen(conf_args, shell=False, env=environ)
+ retcode = configure.wait()
+ if retcode < 0:
+ self.log.error("Child was terminated by signal", -retcode)
+ sys.exit(1)
+ elif retcode != 0:
+ self.log.error("Execution failed: " + string.join(conf_args, ' '))
+ sys.exit(1)
+
+ if not self.options.no_patch:
+ self.phase_patch()
+
+ # Wipe the pre-compiled header, if there is one
+ pch = join(self.build_directory(), 'system.hh.gch')
+ if exists(pch):
+ os.remove(pch)
+ else:
+ if not self.options.no_patch and \
+ self.isnewer('Makefile', '.timestamp'):
+ self.phase_patch()
+
+ self.log.debug('configure does not need to be run')
+
+ finally:
+ os.chdir(self.source_dir)
+
+ def phase_config(self, *args):
+ self.log.info('Executing phase: config')
+ self.phase_submodule()
+ self.phase_autoconf()
+ self.phase_configure(*args)
+ if self.should_clean:
+ self.phase_clean()
+
+ #########################################################################
+ # Builds products from the sources #
+ #########################################################################
+
+ def phase_make(self, *args):
+ self.log.info('Executing phase: make')
+
+ config_args = []
+ make_args = []
+
+ for arg in args:
+ if arg.startswith('--'):
+ config_args.append(arg)
+ else:
+ make_args.append(arg)
+
+ if self.options.jobs > 1:
+ make_args.append('-j%d' % self.options.jobs)
+
+ self.log.debug('Configure arguments => ' + str(config_args))
+ self.log.debug('Makefile arguments => ' + str(make_args))
+
+ if not self.configured:
+ self.phase_config(*config_args)
+
+ build_dir = self.ensure(self.build_directory())
+ try:
+ self.log.debug('Changing directory to ' + build_dir)
+ os.chdir(build_dir)
+
+ self.execute(*(['make'] + make_args))
+ finally:
+ os.chdir(self.source_dir)
+
+ def phase_update(self, *args):
+ self.log.info('Executing phase: update')
+ self.phase_pull()
+ self.phase_make(*args)
+
+ #########################################################################
+ # Build directory cleaning phases #
+ #########################################################################
+
+ def phase_clean(self, *args):
+ self.log.info('Executing phase: clean')
+ self.phase_make('clean')
+
+ def phase_distclean(self, *args):
+ self.log.info('Executing phase: distclean')
+ self.phase_make('distclean')
+
+ def phase_gitclean(self, *args):
+ self.log.info('Executing phase: gitclean')
+ if self.git_working_tree():
+ self.execute('git', 'clean', '-dfx')
+
+ #########################################################################
+ # Packaging phases #
+ #########################################################################
+
+ def translate_file(self, path, dest):
+ dest_file = join(dest, basename(path))
+
+ self.log.debug("Translating file %s -> %s" % (path, dest_file))
+
+ if not exists(dest_file):
+ shutil.copyfile(path, dest_file)
+ os.chmod(dest_file, 0755)
+
+ for line in self.get_stdout('otool', '-L', dest_file).split('\n'):
+ match = re.search('/opt/local/lib/(.+?)\.dylib', line)
+ if not match:
+ continue
+
+ lib = match.group(0)
+ base = basename(lib)
+
+ if lib != path:
+ self.translate_file(lib, dest)
+
+ self.execute('install_name_tool', '-change', lib,
+ '@loader_path/' + base, dest_file)
+
+ def phase_bindmg(self, *args):
+ self.log.info('Executing phase: bindmg')
+
+ self.phase_make()
+
+ binary = join(self.build_directory(), 'ledger')
+ if not exists(binary):
+ self.log.error('Failed to build Ledger: ' + binary)
+ sys.exit(1)
+
+ cwd = os.getcwd()
+ tempdir = tempfile.mkdtemp()
+ try:
+ name = 'ledger-%s' % self.current_version()
+ dest = join(tempdir, name)
+
+ os.makedirs(dest)
+ self.translate_file(binary, dest)
+
+ self.execute('hdiutil', 'create', '-srcfolder', dest,
+ '-ov', join(cwd, name + '.dmg'))
+ finally:
+ os.chdir(cwd)
+ shutil.rmtree(tempdir)
+
+ def phase_upload(self, *args):
+ self.log.info('Executing phase: upload')
+
+ self.phase_bindmg()
+
+ dmg = 'ledger-%s.dmg' % self.current_version()
+ self.execute('zip', '%s.zip' % dmg, dmg)
+ dmg = '%s.zip' % dmg
+
+ self.execute('ssh', 'jw', 'rm', '-f', '/srv/ftp/pub/ledger/ledger-*.dmg.zip')
+ self.execute('scp', dmg, 'jw:/srv/ftp/pub/ledger')
+ self.execute('ssh', 'jw',
+ '(cd /srv/ftp/pub/ledger; ln -sf %s ledger-current.dmg.zip)' %
+ basename(dmg))
+
+ #########################################################################
+ # Other build phases #
+ #########################################################################
+
+ def configure_flavor(self, flavor, reset=True):
+ self.initialize() # reset everything
+ self.build_dir = None # use the build/ tree
+ self.current_flavor = flavor
+
+ if reset and exists(self.build_directory()) and \
+ isdir(self.build_directory()):
+ self.option_release()
+
+ self.log.info('=== Wiping build directory %s ===' %
+ self.build_directory())
+ shutil.rmtree(self.build_directory())
+
+ def phase_distcheck(self, *args):
+ self.log.info('Executing phase: distcheck')
+
+ self.configure_flavor('default', False)
+
+ environ, conf_args = self.configure_environment()
+
+ configure_args = []
+
+ skip_next = False
+ for arg in conf_args[2:]: # skip "sh configure"
+ if arg == '--srcdir':
+ skip_next = True
+ elif skip_next:
+ skip_next = False
+ else:
+ configure_args.append('"' + self.escape_string(arg) + '"')
+
+ make_args = ['DISTCHECK_CONFIGURE_FLAGS=%s' %
+ string.join(configure_args, ' '), 'distcheck']
+
+ self.log.debug('make_args for distcheck => ' + str(make_args))
+
+ self.phase_make(*make_args)
+
+ def phase_rsync(self, *args):
+ self.log.info('Executing phase: rsync')
+
+ source_copy_dir = join(self.ensure(self.products_directory()),
+ 'ledger-proof')
+
+ self.execute('rsync', '-a', '--delete',
+ '--exclude=.git/', '--exclude=b/',
+ '%s/' % self.source_dir, '%s/' % source_copy_dir)
+
+ self.source_dir = source_copy_dir
+
+ def phase_proof(self, *args):
+ self.log.info('Executing phase: proof')
+
+ self.log.info('=== Copying source tree ===')
+ self.phase_rsync()
+ self.phase_makeall(reset=True, *args)
+
+ self.configure_flavor('opt')
+ self.log.info('=== Testing opt ===')
+ self.phase_make('fullcheck')
+
+ self.configure_flavor('gcov')
+ self.log.info('=== Testing gcov ===')
+ self.phase_make('check')
+
+ self.configure_flavor('debug')
+ self.log.info('=== Testing debug ===')
+ self.phase_make('fullcheck')
+
+ self.configure_flavor('default')
+ self.log.info('=== Testing default ===')
+ self.phase_make('fullcheck')
+
+ self.log.info('=== Building final distcheck ===')
+ self.phase_distcheck()
+
+ def phase_makeall(self, reset=False, *args):
+ self.log.info('Executing phase: makeall')
+
+ self.configure_flavor('opt', reset)
+
+ system_hh_gch = join(self.source_dir, 'src', 'system.hh.gch')
+ if exists(system_hh_gch):
+ os.remove(system_hh_gch)
+
+ self.log.info('=== Building opt ===')
+ self.phase_make(*args)
+
+ self.configure_flavor('gcov', reset)
+
+ system_hh_gch = join(self.source_dir, 'src', 'system.hh.gch')
+ if exists(system_hh_gch):
+ os.remove(system_hh_gch)
+
+ self.log.info('=== Building gcov ===')
+ self.phase_make(*args)
+
+ system_hh_gch = join(self.source_dir, 'src', 'system.hh.gch')
+ if exists(system_hh_gch):
+ os.remove(system_hh_gch)
+
+ self.log.info('=== Building default ===')
+ self.phase_make(*args)
+
+ self.configure_flavor('debug', reset)
+
+ system_hh_gch = join(self.source_dir, 'src', 'system.hh.gch')
+ if exists(system_hh_gch):
+ os.remove(system_hh_gch)
+
+ self.log.info('=== Building debug ===')
+ self.phase_make(*args)
+
+ self.configure_flavor('default', reset)
+
+ #########################################################################
+ # Help #
+ #########################################################################
+
+ def phase_help(self, *args):
+ self.option_parser.print_help()
+
+ print """
+Of the optional ARGS, the first is an optional build FLAVOR, with the default
+being 'debug':
+
+ default Regular autoconf settings
+ debug Debugging and --verify support (default)
+ opt Full optimizations
+ gcov Coverage analysis
+ gprof Code profiling (for OS X, just use: 'shark -i ledger ...')
+
+Next is the optional build PHASE, with 'config' being the default:
+
+ clean Runs 'make clean' in the build directory
+ config Configure the environment for building
+ dependencies Automatically install all necessary build dependencies
+ distcheck Properly does 'make distcheck', carrying all flags
+ distclean Runs 'make distclean' in the build directory
+ gitclean Runs 'git clean -dfx', which *really* cleans things
+ help Displays this help text
+ info Show information about the build environment
+ make Do a make in the build directory
+ proof Proves Ledger by building and testing every flavor
+ pull Pulls the latest, and updates local config if need be
+ update Does it all, updates your environment and re-make's
+
+There are many other build phases, though most are not of interest to the
+typical user:
+
+ aclocal Runs aclocal -I m4
+ autoconf Prepare the autoconf subsystem
+ autogen Runs autogen.sh
+ configure Runs just ./configure
+ do_all Runs makeall followed by proof
+ gettext Initialize gettext support
+ makeall Build every flavor there is
+ patch Patches the automake Makefile to be less verbose
+ products Report the products directory path
+ rsync Rsync a copy of the source tree into Products
+ sloc Report total Source Lines Of Code
+ submodule Updates Git submodules (better to use 'pull')
+ version Output current HEAD version to version.m4
+
+NOTE: If you wish to pass options to configure or make, add "--" followed by
+your options. Here are some real-world examples:
+
+ ./acprep
+ ./acprep opt -- make -j3
+ ./acprep -- --enable-doxygen"""
+ sys.exit(0)
+
+PrepareBuild().run()
diff --git a/amount.cc b/amount.cc
deleted file mode 100644
index ee9f78b0..00000000
--- a/amount.cc
+++ /dev/null
@@ -1,2018 +0,0 @@
-#include "amount.h"
-#include "util.h"
-
-#include <list>
-#include <sstream>
-#include <cstdlib>
-#include <memory>
-
-#include <gmp.h>
-
-namespace ledger {
-
-bool do_cleanup = true;
-
-bool amount_t::keep_price = false;
-bool amount_t::keep_date = false;
-bool amount_t::keep_tag = false;
-bool amount_t::keep_base = false;
-
-#define BIGINT_BULK_ALLOC 0x0001
-#define BIGINT_KEEP_PREC 0x0002
-
-class amount_t::bigint_t {
- public:
- mpz_t val;
- unsigned char prec;
- unsigned char flags;
- unsigned int ref;
- unsigned int index;
-
- bigint_t() : prec(0), flags(0), ref(1), index(0) {
- mpz_init(val);
- }
- bigint_t(mpz_t _val) : prec(0), flags(0), ref(1), index(0) {
- mpz_init_set(val, _val);
- }
- bigint_t(const bigint_t& other)
- : prec(other.prec), flags(other.flags & BIGINT_KEEP_PREC),
- ref(1), index(0) {
- mpz_init_set(val, other.val);
- }
- ~bigint_t();
-};
-
-unsigned int sizeof_bigint_t() {
- return sizeof(amount_t::bigint_t);
-}
-
-#define MPZ(x) ((x)->val)
-
-static mpz_t temp; // these are the global temp variables
-static mpz_t divisor;
-
-static amount_t::bigint_t true_value;
-
-inline amount_t::bigint_t::~bigint_t() {
- assert(ref == 0 || (! do_cleanup && this == &true_value));
- mpz_clear(val);
-}
-
-base_commodities_map commodity_base_t::commodities;
-
-commodity_base_t::updater_t * commodity_base_t::updater = NULL;
-
-commodities_map commodity_t::commodities;
-bool commodity_t::commodities_sorted = false;
-commodity_t * commodity_t::null_commodity;
-commodity_t * commodity_t::default_commodity = NULL;
-
-static struct _init_amounts {
- _init_amounts() {
- mpz_init(temp);
- mpz_init(divisor);
-
- mpz_set_ui(true_value.val, 1);
-
- commodity_base_t::updater = NULL;
- commodity_t::null_commodity = commodity_t::create("");
- commodity_t::default_commodity = NULL;
-
- commodity_t::null_commodity->add_flags(COMMODITY_STYLE_NOMARKET |
- COMMODITY_STYLE_BUILTIN);
-
- // Add time commodity conversions, so that timelog's may be parsed
- // in terms of seconds, but reported as minutes or hours.
- commodity_t * commodity;
-
- commodity = commodity_t::create("s");
- commodity->add_flags(COMMODITY_STYLE_NOMARKET | COMMODITY_STYLE_BUILTIN);
-
- parse_conversion("1.0m", "60s");
- parse_conversion("1.0h", "60m");
-
-#if 0
- commodity = commodity_t::create("b");
- commodity->add_flags(COMMODITY_STYLE_NOMARKET | COMMODITY_STYLE_BUILTIN);
-
- parse_conversion("1.00 Kb", "1024 b");
- parse_conversion("1.00 Mb", "1024 Kb");
- parse_conversion("1.00 Gb", "1024 Mb");
- parse_conversion("1.00 Tb", "1024 Gb");
-#endif
- }
-
- ~_init_amounts() {
- if (! do_cleanup)
- return;
-
- mpz_clear(temp);
- mpz_clear(divisor);
-
- if (commodity_base_t::updater) {
- delete commodity_base_t::updater;
- commodity_base_t::updater = NULL;
- }
-
- for (commodities_map::iterator i = commodity_t::commodities.begin();
- i != commodity_t::commodities.end();
- i++)
- delete (*i).second;
-
- commodity_t::commodities.clear();
-
- true_value.ref--;
- }
-} _init_obj;
-
-static void mpz_round(mpz_t out, mpz_t value, int value_prec, int round_prec)
-{
- // Round `value', with an encoding precision of `value_prec', to a
- // rounded value with precision `round_prec'. Result is stored in
- // `out'.
-
- assert(value_prec > round_prec);
-
- mpz_t quotient;
- mpz_t remainder;
-
- mpz_init(quotient);
- mpz_init(remainder);
-
- mpz_ui_pow_ui(divisor, 10, value_prec - round_prec);
- mpz_tdiv_qr(quotient, remainder, value, divisor);
- mpz_divexact_ui(divisor, divisor, 10);
- mpz_mul_ui(divisor, divisor, 5);
-
- if (mpz_sgn(remainder) < 0) {
- mpz_neg(divisor, divisor);
- if (mpz_cmp(remainder, divisor) < 0) {
- mpz_ui_pow_ui(divisor, 10, value_prec - round_prec);
- mpz_add(remainder, divisor, remainder);
- mpz_ui_sub(remainder, 0, remainder);
- mpz_add(out, value, remainder);
- } else {
- mpz_sub(out, value, remainder);
- }
- } else {
- if (mpz_cmp(remainder, divisor) >= 0) {
- mpz_ui_pow_ui(divisor, 10, value_prec - round_prec);
- mpz_sub(remainder, divisor, remainder);
- mpz_add(out, value, remainder);
- } else {
- mpz_sub(out, value, remainder);
- }
- }
- mpz_clear(quotient);
- mpz_clear(remainder);
-
- // chop off the rounded bits
- mpz_ui_pow_ui(divisor, 10, value_prec - round_prec);
- mpz_tdiv_q(out, out, divisor);
-}
-
-amount_t::amount_t(const bool value)
-{
- if (value) {
- quantity = &true_value;
- quantity->ref++;
- } else {
- quantity = NULL;
- }
- commodity_ = NULL;
-}
-
-amount_t::amount_t(const long value)
-{
- if (value != 0) {
- quantity = new bigint_t;
- mpz_set_si(MPZ(quantity), value);
- } else {
- quantity = NULL;
- }
- commodity_ = NULL;
-}
-
-amount_t::amount_t(const unsigned long value)
-{
- if (value != 0) {
- quantity = new bigint_t;
- mpz_set_ui(MPZ(quantity), value);
- } else {
- quantity = NULL;
- }
- commodity_ = NULL;
-}
-
-amount_t::amount_t(const double value)
-{
- if (value != 0.0) {
- quantity = new bigint_t;
- mpz_set_d(MPZ(quantity), value);
- } else {
- quantity = NULL;
- }
- commodity_ = NULL;
-}
-
-void amount_t::_release()
-{
- DEBUG_PRINT("amounts.refs",
- quantity << " ref--, now " << (quantity->ref - 1));
- if (--quantity->ref == 0) {
- if (! (quantity->flags & BIGINT_BULK_ALLOC))
- delete quantity;
- else
- quantity->~bigint_t();
- }
-}
-
-void amount_t::_init()
-{
- if (! quantity) {
- quantity = new bigint_t;
- }
- else if (quantity->ref > 1) {
- _release();
- quantity = new bigint_t;
- }
-}
-
-void amount_t::_dup()
-{
- if (quantity->ref > 1) {
- bigint_t * q = new bigint_t(*quantity);
- _release();
- quantity = q;
- }
-}
-
-void amount_t::_copy(const amount_t& amt)
-{
- if (quantity != amt.quantity) {
- if (quantity)
- _release();
-
- // Never maintain a pointer into a bulk allocation pool; such
- // pointers are not guaranteed to remain.
- if (amt.quantity->flags & BIGINT_BULK_ALLOC) {
- quantity = new bigint_t(*amt.quantity);
- } else {
- quantity = amt.quantity;
- DEBUG_PRINT("amounts.refs",
- quantity << " ref++, now " << (quantity->ref + 1));
- quantity->ref++;
- }
- }
- commodity_ = amt.commodity_;
-}
-
-amount_t& amount_t::operator=(const std::string& value)
-{
- std::istringstream str(value);
- parse(str);
- return *this;
-}
-
-amount_t& amount_t::operator=(const char * value)
-{
- std::string valstr(value);
- std::istringstream str(valstr);
- parse(str);
- return *this;
-}
-
-// assignment operator
-amount_t& amount_t::operator=(const amount_t& amt)
-{
- if (this != &amt) {
- if (amt.quantity)
- _copy(amt);
- else if (quantity)
- _clear();
- }
- return *this;
-}
-
-amount_t& amount_t::operator=(const bool value)
-{
- if (! value) {
- if (quantity)
- _clear();
- } else {
- commodity_ = NULL;
- if (quantity)
- _release();
- quantity = &true_value;
- quantity->ref++;
- }
- return *this;
-}
-
-amount_t& amount_t::operator=(const long value)
-{
- if (value == 0) {
- if (quantity)
- _clear();
- } else {
- commodity_ = NULL;
- _init();
- mpz_set_si(MPZ(quantity), value);
- }
- return *this;
-}
-
-amount_t& amount_t::operator=(const unsigned long value)
-{
- if (value == 0) {
- if (quantity)
- _clear();
- } else {
- commodity_ = NULL;
- _init();
- mpz_set_ui(MPZ(quantity), value);
- }
- return *this;
-}
-
-amount_t& amount_t::operator=(const double value)
-{
- if (value == 0.0) {
- if (quantity)
- _clear();
- } else {
- commodity_ = NULL;
- _init();
- mpz_set_d(MPZ(quantity), value);
- }
- return *this;
-}
-
-
-void amount_t::_resize(unsigned int prec)
-{
- assert(prec < 256);
-
- if (! quantity || prec == quantity->prec)
- return;
-
- _dup();
-
- if (prec < quantity->prec) {
- mpz_ui_pow_ui(divisor, 10, quantity->prec - prec);
- mpz_tdiv_q(MPZ(quantity), MPZ(quantity), divisor);
- } else {
- mpz_ui_pow_ui(divisor, 10, prec - quantity->prec);
- mpz_mul(MPZ(quantity), MPZ(quantity), divisor);
- }
-
- quantity->prec = prec;
-}
-
-
-amount_t& amount_t::operator+=(const amount_t& amt)
-{
- if (! amt.quantity)
- return *this;
-
- if (! quantity) {
- _copy(amt);
- return *this;
- }
-
- _dup();
-
- if (commodity() != amt.commodity())
- throw new amount_error
- (std::string("Adding amounts with different commodities: ") +
- commodity_->qualified_symbol + " != " +
- amt.commodity_->qualified_symbol);
-
- if (quantity->prec == amt.quantity->prec) {
- mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
- }
- else if (quantity->prec < amt.quantity->prec) {
- _resize(amt.quantity->prec);
- mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
- }
- else {
- amount_t temp = amt;
- temp._resize(quantity->prec);
- mpz_add(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity));
- }
-
- return *this;
-}
-
-amount_t& amount_t::operator-=(const amount_t& amt)
-{
- if (! amt.quantity)
- return *this;
-
- if (! quantity) {
- quantity = new bigint_t(*amt.quantity);
- commodity_ = amt.commodity_;
- mpz_neg(MPZ(quantity), MPZ(quantity));
- return *this;
- }
-
- _dup();
-
- if (commodity() != amt.commodity())
- throw new amount_error
- (std::string("Subtracting amounts with different commodities: ") +
- commodity_->qualified_symbol + " != " +
- amt.commodity_->qualified_symbol);
-
- if (quantity->prec == amt.quantity->prec) {
- mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
- }
- else if (quantity->prec < amt.quantity->prec) {
- _resize(amt.quantity->prec);
- mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
- }
- else {
- amount_t temp = amt;
- temp._resize(quantity->prec);
- mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity));
- }
-
- return *this;
-}
-
-amount_t& amount_t::operator*=(const amount_t& amt)
-{
- if (! amt.quantity)
- return (*this = amt);
- else if (! quantity)
- return *this;
-
- _dup();
-
- mpz_mul(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
- quantity->prec += amt.quantity->prec;
-
- unsigned int comm_prec = commodity().precision();
- if (quantity->prec > comm_prec + 6U) {
- mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U);
- quantity->prec = comm_prec + 6U;
- }
-
- return *this;
-}
-
-amount_t& amount_t::operator/=(const amount_t& amt)
-{
- if (! amt.quantity || ! amt)
- throw new amount_error("Divide by zero");
- else if (! quantity)
- return *this;
-
- _dup();
-
- // Increase the value's precision, to capture fractional parts after
- // the divide.
- mpz_ui_pow_ui(divisor, 10, amt.quantity->prec + 6U);
- mpz_mul(MPZ(quantity), MPZ(quantity), divisor);
- mpz_tdiv_q(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
- quantity->prec += 6U;
-
- unsigned int comm_prec = commodity().precision();
- if (quantity->prec > comm_prec + 6U) {
- mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U);
- quantity->prec = comm_prec + 6U;
- }
-
- return *this;
-}
-
-// unary negation
-void amount_t::negate()
-{
- if (quantity) {
- _dup();
- mpz_neg(MPZ(quantity), MPZ(quantity));
- }
-}
-
-int amount_t::sign() const
-{
- return quantity ? mpz_sgn(MPZ(quantity)) : 0;
-}
-
-int amount_t::compare(const amount_t& amt) const
-{
- if (! quantity) {
- if (! amt.quantity)
- return 0;
- return - amt.sign();
- }
- if (! amt.quantity)
- return sign();
-
- if (commodity() && amt.commodity() && commodity() != amt.commodity())
- throw new amount_error
- (std::string("Cannot compare amounts with different commodities: ") +
- commodity().symbol() + " and " + amt.commodity().symbol());
-
- if (quantity->prec == amt.quantity->prec) {
- return mpz_cmp(MPZ(quantity), MPZ(amt.quantity));
- }
- else if (quantity->prec < amt.quantity->prec) {
- amount_t temp = *this;
- temp._resize(amt.quantity->prec);
- return mpz_cmp(MPZ(temp.quantity), MPZ(amt.quantity));
- }
- else {
- amount_t temp = amt;
- temp._resize(quantity->prec);
- return mpz_cmp(MPZ(quantity), MPZ(temp.quantity));
- }
-}
-
-bool amount_t::operator==(const amount_t& amt) const
-{
- if (commodity() != amt.commodity())
- return false;
- return compare(amt) == 0;
-}
-
-bool amount_t::operator!=(const amount_t& amt) const
-{
- if (commodity() != amt.commodity())
- return true;
- return compare(amt) != 0;
-}
-
-amount_t::operator bool() const
-{
- if (! quantity)
- return false;
-
- if (quantity->prec <= commodity().precision() ||
- (quantity->flags & BIGINT_KEEP_PREC)) {
- return mpz_sgn(MPZ(quantity)) != 0;
- } else {
- mpz_set(temp, MPZ(quantity));
- mpz_ui_pow_ui(divisor, 10, quantity->prec - commodity().precision());
- mpz_tdiv_q(temp, temp, divisor);
- bool zero = mpz_sgn(temp) == 0;
- return ! zero;
- }
-}
-
-amount_t::operator long() const
-{
- if (! quantity)
- return 0;
-
- mpz_set(temp, MPZ(quantity));
- mpz_ui_pow_ui(divisor, 10, quantity->prec);
- mpz_tdiv_q(temp, temp, divisor);
- return mpz_get_si(temp);
-}
-
-amount_t::operator double() const
-{
- if (! quantity)
- return 0.0;
-
- mpz_t remainder;
- mpz_init(remainder);
-
- mpz_set(temp, MPZ(quantity));
- mpz_ui_pow_ui(divisor, 10, quantity->prec);
- mpz_tdiv_qr(temp, remainder, temp, divisor);
-
- char * quotient_s = mpz_get_str(NULL, 10, temp);
- char * remainder_s = mpz_get_str(NULL, 10, remainder);
-
- std::ostringstream num;
- num << quotient_s << '.' << remainder_s;
-
- std::free(quotient_s);
- std::free(remainder_s);
-
- mpz_clear(remainder);
-
- return std::atof(num.str().c_str());
-}
-
-bool amount_t::realzero() const
-{
- if (! quantity)
- return true;
- return mpz_sgn(MPZ(quantity)) == 0;
-}
-
-amount_t amount_t::value(const datetime_t& moment) const
-{
- if (quantity) {
- amount_t amt(commodity().value(moment));
- if (! amt.realzero())
- return (amt * *this).round();
- }
- return *this;
-}
-
-amount_t amount_t::round(unsigned int prec) const
-{
- amount_t temp = *this;
-
- if (! quantity || quantity->prec <= prec) {
- if (quantity && quantity->flags & BIGINT_KEEP_PREC) {
- temp._dup();
- temp.quantity->flags &= ~BIGINT_KEEP_PREC;
- }
- return temp;
- }
-
- temp._dup();
-
- mpz_round(MPZ(temp.quantity), MPZ(temp.quantity), temp.quantity->prec, prec);
-
- temp.quantity->prec = prec;
- temp.quantity->flags &= ~BIGINT_KEEP_PREC;
-
- return temp;
-}
-
-amount_t amount_t::unround() const
-{
- if (! quantity) {
- amount_t temp(0L);
- assert(temp.quantity);
- temp.quantity->flags |= BIGINT_KEEP_PREC;
- return temp;
- }
- else if (quantity->flags & BIGINT_KEEP_PREC) {
- return *this;
- }
-
- amount_t temp = *this;
- temp._dup();
- temp.quantity->flags |= BIGINT_KEEP_PREC;
-
- return temp;
-}
-
-std::string amount_t::quantity_string() const
-{
- if (! quantity)
- return "0";
-
- std::ostringstream out;
-
- mpz_t quotient;
- mpz_t rquotient;
- mpz_t remainder;
-
- mpz_init(quotient);
- mpz_init(rquotient);
- mpz_init(remainder);
-
- bool negative = false;
-
- // Ensure the value is rounded to the commodity's precision before
- // outputting it. NOTE: `rquotient' is used here as a temp variable!
-
- commodity_t& comm(commodity());
- unsigned char precision;
-
- if (! comm || quantity->flags & BIGINT_KEEP_PREC) {
- mpz_ui_pow_ui(divisor, 10, quantity->prec);
- mpz_tdiv_qr(quotient, remainder, MPZ(quantity), divisor);
- precision = quantity->prec;
- }
- else if (comm.precision() < quantity->prec) {
- mpz_round(rquotient, MPZ(quantity), quantity->prec, comm.precision());
- mpz_ui_pow_ui(divisor, 10, comm.precision());
- mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
- precision = comm.precision();
- }
- else if (comm.precision() > quantity->prec) {
- mpz_ui_pow_ui(divisor, 10, comm.precision() - quantity->prec);
- mpz_mul(rquotient, MPZ(quantity), divisor);
- mpz_ui_pow_ui(divisor, 10, comm.precision());
- mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
- precision = comm.precision();
- }
- else if (quantity->prec) {
- mpz_ui_pow_ui(divisor, 10, quantity->prec);
- mpz_tdiv_qr(quotient, remainder, MPZ(quantity), divisor);
- precision = quantity->prec;
- }
- else {
- mpz_set(quotient, MPZ(quantity));
- mpz_set_ui(remainder, 0);
- precision = 0;
- }
-
- if (mpz_sgn(quotient) < 0 || mpz_sgn(remainder) < 0) {
- negative = true;
-
- mpz_abs(quotient, quotient);
- mpz_abs(remainder, remainder);
- }
- mpz_set(rquotient, remainder);
-
- if (mpz_sgn(quotient) == 0 && mpz_sgn(rquotient) == 0)
- return "0";
-
- if (negative)
- out << "-";
-
- if (mpz_sgn(quotient) == 0) {
- out << '0';
- } else {
- char * p = mpz_get_str(NULL, 10, quotient);
- out << p;
- std::free(p);
- }
-
- if (precision) {
- out << '.';
-
- out.width(precision);
- out.fill('0');
-
- char * p = mpz_get_str(NULL, 10, rquotient);
- out << p;
- std::free(p);
- }
-
- mpz_clear(quotient);
- mpz_clear(rquotient);
- mpz_clear(remainder);
-
- return out.str();
-}
-
-std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
-{
- if (! amt.quantity) {
- _out << "0";
- return _out;
- }
-
- amount_t base(amt);
- if (! amount_t::keep_base && amt.commodity().larger()) {
- amount_t last(amt);
- while (last.commodity().larger()) {
- last /= *last.commodity().larger();
- last.commodity_ = last.commodity().larger()->commodity_;
- if (ledger::abs(last) < 1)
- break;
- base = last.round();
- }
- }
-
- std::ostringstream out;
-
- mpz_t quotient;
- mpz_t rquotient;
- mpz_t remainder;
-
- mpz_init(quotient);
- mpz_init(rquotient);
- mpz_init(remainder);
-
- bool negative = false;
-
- // Ensure the value is rounded to the commodity's precision before
- // outputting it. NOTE: `rquotient' is used here as a temp variable!
-
- commodity_t& comm(base.commodity());
- unsigned char precision;
-
- if (! comm || base.quantity->flags & BIGINT_KEEP_PREC) {
- mpz_ui_pow_ui(divisor, 10, base.quantity->prec);
- mpz_tdiv_qr(quotient, remainder, MPZ(base.quantity), divisor);
- precision = base.quantity->prec;
- }
- else if (comm.precision() < base.quantity->prec) {
- mpz_round(rquotient, MPZ(base.quantity), base.quantity->prec,
- comm.precision());
- mpz_ui_pow_ui(divisor, 10, comm.precision());
- mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
- precision = comm.precision();
- }
- else if (comm.precision() > base.quantity->prec) {
- mpz_ui_pow_ui(divisor, 10, comm.precision() - base.quantity->prec);
- mpz_mul(rquotient, MPZ(base.quantity), divisor);
- mpz_ui_pow_ui(divisor, 10, comm.precision());
- mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
- precision = comm.precision();
- }
- else if (base.quantity->prec) {
- mpz_ui_pow_ui(divisor, 10, base.quantity->prec);
- mpz_tdiv_qr(quotient, remainder, MPZ(base.quantity), divisor);
- precision = base.quantity->prec;
- }
- else {
- mpz_set(quotient, MPZ(base.quantity));
- mpz_set_ui(remainder, 0);
- precision = 0;
- }
-
- if (mpz_sgn(quotient) < 0 || mpz_sgn(remainder) < 0) {
- negative = true;
-
- mpz_abs(quotient, quotient);
- mpz_abs(remainder, remainder);
- }
- mpz_set(rquotient, remainder);
-
- if (mpz_sgn(quotient) == 0 && mpz_sgn(rquotient) == 0) {
- _out << "0";
- return _out;
- }
-
- if (! (comm.flags() & COMMODITY_STYLE_SUFFIXED)) {
- comm.write(out);
-
- if (comm.flags() & COMMODITY_STYLE_SEPARATED)
- out << " ";
- }
-
- if (negative)
- out << "-";
-
- if (mpz_sgn(quotient) == 0) {
- out << '0';
- }
- else if (! (comm.flags() & COMMODITY_STYLE_THOUSANDS)) {
- char * p = mpz_get_str(NULL, 10, quotient);
- out << p;
- std::free(p);
- }
- else {
- std::list<std::string> strs;
- char buf[4];
-
- for (int powers = 0; true; powers += 3) {
- if (powers > 0) {
- mpz_ui_pow_ui(divisor, 10, powers);
- mpz_tdiv_q(temp, quotient, divisor);
- if (mpz_sgn(temp) == 0)
- break;
- mpz_tdiv_r_ui(temp, temp, 1000);
- } else {
- mpz_tdiv_r_ui(temp, quotient, 1000);
- }
- mpz_get_str(buf, 10, temp);
- strs.push_back(buf);
- }
-
- bool printed = false;
-
- for (std::list<std::string>::reverse_iterator i = strs.rbegin();
- i != strs.rend();
- i++) {
- if (printed) {
- out << (comm.flags() & COMMODITY_STYLE_EUROPEAN ? '.' : ',');
- out.width(3);
- out.fill('0');
- }
- out << *i;
-
- printed = true;
- }
- }
-
- if (precision) {
- std::ostringstream final;
- final.width(precision);
- final.fill('0');
- char * p = mpz_get_str(NULL, 10, rquotient);
- final << p;
- std::free(p);
-
- const std::string& str(final.str());
- int i, len = str.length();
- const char * q = str.c_str();
- for (i = len; i > 0; i--)
- if (q[i - 1] != '0')
- break;
-
- std::string ender;
- if (i == len)
- ender = str;
- else if (i < comm.precision())
- ender = std::string(str, 0, comm.precision());
- else
- ender = std::string(str, 0, i);
-
- if (! ender.empty()) {
- out << ((comm.flags() & COMMODITY_STYLE_EUROPEAN) ? ',' : '.');
- out << ender;
- }
- }
-
- if (comm.flags() & COMMODITY_STYLE_SUFFIXED) {
- if (comm.flags() & COMMODITY_STYLE_SEPARATED)
- out << " ";
-
- comm.write(out);
- }
-
- mpz_clear(quotient);
- mpz_clear(rquotient);
- mpz_clear(remainder);
-
- // If there are any annotations associated with this commodity,
- // output them now.
-
- if (comm.annotated) {
- annotated_commodity_t& ann(static_cast<annotated_commodity_t&>(comm));
- assert(&ann.price != &amt);
- ann.write_annotations(out);
- }
-
- // Things are output to a string first, so that if anyone has
- // specified a width or fill for _out, it will be applied to the
- // entire amount string, and not just the first part.
-
- _out << out.str();
-
- return _out;
-}
-
-void parse_quantity(std::istream& in, std::string& value)
-{
- char buf[256];
- char c = peek_next_nonws(in);
- READ_INTO(in, buf, 255, c,
- std::isdigit(c) || c == '-' || c == '.' || c == ',');
-
- int len = std::strlen(buf);
- while (len > 0 && ! std::isdigit(buf[len - 1])) {
- buf[--len] = '\0';
- in.unget();
- }
-
- value = buf;
-}
-
-// Invalid commodity characters:
-// SPACE, TAB, NEWLINE, RETURN
-// 0-9 . , ; - + * / ^ ? : & | ! =
-// < > { } [ ] ( ) @
-
-int invalid_chars[256] = {
- /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
-/* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
-/* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* 20 */ 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 40 */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
-/* 60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
-/* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* a0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* b0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* c0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* d0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* e0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* f0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-void parse_commodity(std::istream& in, std::string& symbol)
-{
- char buf[256];
- char c = peek_next_nonws(in);
- if (c == '"') {
- in.get(c);
- READ_INTO(in, buf, 255, c, c != '"');
- if (c == '"')
- in.get(c);
- else
- throw new amount_error("Quoted commodity symbol lacks closing quote");
- } else {
- READ_INTO(in, buf, 255, c, ! invalid_chars[(unsigned char)c]);
- }
- symbol = buf;
-}
-
-void parse_annotations(std::istream& in, amount_t& price,
- datetime_t& date, std::string& tag)
-{
- do {
- char buf[256];
- char c = peek_next_nonws(in);
- if (c == '{') {
- if (price)
- throw new amount_error("Commodity specifies more than one price");
-
- in.get(c);
- READ_INTO(in, buf, 255, c, c != '}');
- if (c == '}')
- in.get(c);
- else
- throw new amount_error("Commodity price lacks closing brace");
-
- price.parse(buf, AMOUNT_PARSE_NO_MIGRATE);
- price.reduce();
-
- // Since this price will maintain its own precision, make sure
- // it is at least as large as the base commodity, since the user
- // may have only specified {$1} or something similar.
-
- if (price.quantity->prec < price.commodity().precision())
- price = price.round(); // no need to retain individual precision
- }
- else if (c == '[') {
- if (date)
- throw new amount_error("Commodity specifies more than one date");
-
- in.get(c);
- READ_INTO(in, buf, 255, c, c != ']');
- if (c == ']')
- in.get(c);
- else
- throw new amount_error("Commodity date lacks closing bracket");
-
- date = buf;
- }
- else if (c == '(') {
- if (! tag.empty())
- throw new amount_error("Commodity specifies more than one tag");
-
- in.get(c);
- READ_INTO(in, buf, 255, c, c != ')');
- if (c == ')')
- in.get(c);
- else
- throw new amount_error("Commodity tag lacks closing parenthesis");
-
- tag = buf;
- }
- else {
- break;
- }
- } while (true);
-
- DEBUG_PRINT("amounts.commodities",
- "Parsed commodity annotations: "
- << " price " << price << " "
- << " date " << date << " "
- << " tag " << tag);
-}
-
-bool amount_t::parse(std::istream& in, unsigned char flags)
-{
- // The possible syntax for an amount is:
- //
- // [-]NUM[ ]SYM [@ AMOUNT]
- // SYM[ ][-]NUM [@ AMOUNT]
-
- std::string symbol;
- std::string quant;
- amount_t price;
- datetime_t date;
- std::string tag;
- unsigned int comm_flags = COMMODITY_STYLE_DEFAULTS;
- bool negative = false;
-
- char c = peek_next_nonws(in);
- if (c == '-') {
- negative = true;
- in.get(c);
- c = peek_next_nonws(in);
- }
-
- char n;
- if (std::isdigit(c)) {
- parse_quantity(in, quant);
-
- if (! in.eof() && ((n = in.peek()) != '\n')) {
- if (std::isspace(n))
- comm_flags |= COMMODITY_STYLE_SEPARATED;
-
- parse_commodity(in, symbol);
-
- if (! symbol.empty())
- comm_flags |= COMMODITY_STYLE_SUFFIXED;
-
- if (! in.eof() && ((n = in.peek()) != '\n'))
- parse_annotations(in, price, date, tag);
- }
- } else {
- parse_commodity(in, symbol);
-
- if (! in.eof() && ((n = in.peek()) != '\n')) {
- if (std::isspace(in.peek()))
- comm_flags |= COMMODITY_STYLE_SEPARATED;
-
- parse_quantity(in, quant);
-
- if (! quant.empty() && ! in.eof() && ((n = in.peek()) != '\n'))
- parse_annotations(in, price, date, tag);
- }
- }
-
- if (quant.empty()) {
- if (flags & AMOUNT_PARSE_SOFT_FAIL)
- return false;
- else
- throw new amount_error("No quantity specified for amount");
- }
-
- _init();
-
- // Create the commodity if has not already been seen, and update the
- // precision if something greater was used for the quantity.
-
- bool newly_created = false;
-
- if (symbol.empty()) {
- commodity_ = commodity_t::null_commodity;
- } else {
- commodity_ = commodity_t::find(symbol);
- if (! commodity_) {
- commodity_ = commodity_t::create(symbol);
- newly_created = true;
- }
- assert(commodity_);
-
- if (! price.realzero() || date || ! tag.empty())
- commodity_ =
- annotated_commodity_t::find_or_create(*commodity_, price, date, tag);
- }
-
- // Determine the precision of the amount, based on the usage of
- // comma or period.
-
- std::string::size_type last_comma = quant.rfind(',');
- std::string::size_type last_period = quant.rfind('.');
-
- if (last_comma != std::string::npos && last_period != std::string::npos) {
- comm_flags |= COMMODITY_STYLE_THOUSANDS;
- if (last_comma > last_period) {
- comm_flags |= COMMODITY_STYLE_EUROPEAN;
- quantity->prec = quant.length() - last_comma - 1;
- } else {
- quantity->prec = quant.length() - last_period - 1;
- }
- }
- else if (last_comma != std::string::npos &&
- (! commodity_t::default_commodity ||
- commodity_t::default_commodity->flags() & COMMODITY_STYLE_EUROPEAN)) {
- comm_flags |= COMMODITY_STYLE_EUROPEAN;
- quantity->prec = quant.length() - last_comma - 1;
- }
- else if (last_period != std::string::npos &&
- ! (commodity().flags() & COMMODITY_STYLE_EUROPEAN)) {
- quantity->prec = quant.length() - last_period - 1;
- }
- else {
- quantity->prec = 0;
- }
-
- // Set the commodity's flags and precision accordingly
-
- if (! (flags & AMOUNT_PARSE_NO_MIGRATE)) {
- commodity().add_flags(comm_flags);
- if (quantity->prec > commodity().precision())
- commodity().set_precision(quantity->prec);
- } else {
- quantity->flags |= BIGINT_KEEP_PREC;
- }
-
- // Now we have the final number. Remove commas and periods, if
- // necessary.
-
- if (last_comma != std::string::npos || last_period != std::string::npos) {
- int len = quant.length();
- char * buf = new char[len + 1];
- const char * p = quant.c_str();
- char * t = buf;
-
- while (*p) {
- if (*p == ',' || *p == '.')
- p++;
- *t++ = *p++;
- }
- *t = '\0';
-
- mpz_set_str(MPZ(quantity), buf, 10);
- delete[] buf;
- } else {
- mpz_set_str(MPZ(quantity), quant.c_str(), 10);
- }
-
- if (negative)
- negate();
-
- if (! (flags & AMOUNT_PARSE_NO_REDUCE))
- reduce();
-
- return true;
-}
-
-void amount_t::reduce()
-{
- while (commodity_ && commodity().smaller()) {
- *this *= *commodity().smaller();
- commodity_ = commodity().smaller()->commodity_;
- }
-}
-
-bool amount_t::parse(const std::string& str, unsigned char flags)
-{
- std::istringstream stream(str);
- parse(stream, flags);
-}
-
-void parse_conversion(const std::string& larger_str,
- const std::string& smaller_str)
-{
- amount_t larger, smaller;
-
- larger.parse(larger_str.c_str(), AMOUNT_PARSE_NO_REDUCE);
- smaller.parse(smaller_str.c_str(), AMOUNT_PARSE_NO_REDUCE);
-
- larger *= smaller;
-
- if (larger.commodity()) {
- larger.commodity().set_smaller(smaller);
- larger.commodity().add_flags(smaller.commodity().flags() |
- COMMODITY_STYLE_NOMARKET);
- }
- if (smaller.commodity())
- smaller.commodity().set_larger(larger);
-}
-
-
-char * bigints;
-char * bigints_next;
-unsigned int bigints_index;
-unsigned int bigints_count;
-
-void amount_t::read_quantity(char *& data)
-{
- char byte = *data++;;
-
- if (byte == 0) {
- quantity = NULL;
- }
- else if (byte == 1) {
- quantity = new((bigint_t *)bigints_next) bigint_t;
- bigints_next += sizeof(bigint_t);
-
- unsigned short len = *((unsigned short *) data);
- data += sizeof(unsigned short);
- mpz_import(MPZ(quantity), len / sizeof(short), 1, sizeof(short),
- 0, 0, data);
- data += len;
-
- char negative = *data++;
- if (negative)
- mpz_neg(MPZ(quantity), MPZ(quantity));
-
- quantity->prec = *((unsigned char *) data);
- data += sizeof(unsigned char);
- quantity->flags = *((unsigned char *) data);
- data += sizeof(unsigned char);
- quantity->flags |= BIGINT_BULK_ALLOC;
- } else {
- unsigned int index = *((unsigned int *) data);
- data += sizeof(unsigned int);
-
- quantity = (bigint_t *) (bigints + (index - 1) * sizeof(bigint_t));
- DEBUG_PRINT("amounts.refs",
- quantity << " ref++, now " << (quantity->ref + 1));
- quantity->ref++;
- }
-}
-
-static char buf[4096];
-
-void amount_t::read_quantity(std::istream& in)
-{
- char byte;
- in.read(&byte, sizeof(byte));
-
- if (byte == 0) {
- quantity = NULL;
- }
- else if (byte == 1) {
- quantity = new bigint_t;
-
- unsigned short len;
- in.read((char *)&len, sizeof(len));
- assert(len < 4096);
- in.read(buf, len);
- mpz_import(MPZ(quantity), len / sizeof(short), 1, sizeof(short),
- 0, 0, buf);
-
- char negative;
- in.read(&negative, sizeof(negative));
- if (negative)
- mpz_neg(MPZ(quantity), MPZ(quantity));
-
- in.read((char *)&quantity->prec, sizeof(quantity->prec));
- in.read((char *)&quantity->flags, sizeof(quantity->flags));
- }
- else {
- assert(0);
- }
-}
-
-void amount_t::write_quantity(std::ostream& out) const
-{
- char byte;
-
- if (! quantity) {
- byte = 0;
- out.write(&byte, sizeof(byte));
- return;
- }
-
- if (quantity->index == 0) {
- quantity->index = ++bigints_index;
- bigints_count++;
-
- byte = 1;
- out.write(&byte, sizeof(byte));
-
- std::size_t size;
- mpz_export(buf, &size, 1, sizeof(short), 0, 0, MPZ(quantity));
- unsigned short len = size * sizeof(short);
- out.write((char *)&len, sizeof(len));
- if (len) {
- assert(len < 4096);
- out.write(buf, len);
- }
-
- byte = mpz_sgn(MPZ(quantity)) < 0 ? 1 : 0;
- out.write(&byte, sizeof(byte));
-
- out.write((char *)&quantity->prec, sizeof(quantity->prec));
- unsigned char flags = quantity->flags & ~BIGINT_BULK_ALLOC;
- assert(sizeof(flags) == sizeof(quantity->flags));
- out.write((char *)&flags, sizeof(flags));
- } else {
- assert(quantity->ref > 1);
-
- // Since this value has already been written, we simply write
- // out a reference to which one it was.
- byte = 2;
- out.write(&byte, sizeof(byte));
- out.write((char *)&quantity->index, sizeof(quantity->index));
- }
-}
-
-bool amount_t::valid() const
-{
- if (quantity) {
- if (quantity->ref == 0) {
- DEBUG_PRINT("ledger.validate", "amount_t: quantity->ref == 0");
- return false;
- }
- }
- else if (commodity_) {
- DEBUG_PRINT("ledger.validate", "amount_t: commodity_ != NULL");
- return false;
- }
- return true;
-}
-
-void amount_t::annotate_commodity(const amount_t& price,
- const datetime_t& date,
- const std::string& tag)
-{
- const commodity_t * this_base;
- annotated_commodity_t * this_ann = NULL;
-
- if (commodity().annotated) {
- this_ann = &static_cast<annotated_commodity_t&>(commodity());
- this_base = this_ann->ptr;
- } else {
- this_base = &commodity();
- }
- assert(this_base);
-
- DEBUG_PRINT("amounts.commodities", "Annotating commodity for amount "
- << *this << std::endl
- << " price " << price << " "
- << " date " << date << " "
- << " tag " << tag);
-
- commodity_t * ann_comm =
- annotated_commodity_t::find_or_create
- (*this_base, ! price && this_ann ? this_ann->price : price,
- ! date && this_ann ? this_ann->date : date,
- tag.empty() && this_ann ? this_ann->tag : tag);
- if (ann_comm)
- set_commodity(*ann_comm);
-
- DEBUG_PRINT("amounts.commodities", " Annotated amount is " << *this);
-}
-
-amount_t amount_t::strip_annotations(const bool _keep_price,
- const bool _keep_date,
- const bool _keep_tag) const
-{
- if (! commodity().annotated ||
- (_keep_price && _keep_date && _keep_tag))
- return *this;
-
- DEBUG_PRINT("amounts.commodities", "Reducing commodity for amount "
- << *this << std::endl
- << " keep price " << _keep_price << " "
- << " keep date " << _keep_date << " "
- << " keep tag " << _keep_tag);
-
- annotated_commodity_t&
- ann_comm(static_cast<annotated_commodity_t&>(commodity()));
- assert(ann_comm.base);
-
- commodity_t * new_comm;
-
- if ((_keep_price && ann_comm.price) ||
- (_keep_date && ann_comm.date) ||
- (_keep_tag && ! ann_comm.tag.empty()))
- {
- new_comm = annotated_commodity_t::find_or_create
- (*ann_comm.ptr, _keep_price ? ann_comm.price : amount_t(),
- _keep_date ? ann_comm.date : datetime_t(),
- _keep_tag ? ann_comm.tag : "");
- } else {
- new_comm = commodity_t::find_or_create(ann_comm.base_symbol());
- }
- assert(new_comm);
-
- amount_t temp(*this);
- temp.set_commodity(*new_comm);
-
- DEBUG_PRINT("amounts.commodities", " Reduced amount is " << temp);
-
- return temp;
-}
-
-amount_t amount_t::price() const
-{
- if (commodity_ && commodity_->annotated) {
- amount_t temp(((annotated_commodity_t *)commodity_)->price);
- temp *= *this;
- DEBUG_PRINT("amounts.commodities",
- "Returning price of " << *this << " = " << temp);
- return temp;
- }
- return *this;
-}
-
-datetime_t amount_t::date() const
-{
- if (commodity_ && commodity_->annotated) {
- DEBUG_PRINT("amounts.commodities",
- "Returning date of " << *this << " = "
- << ((annotated_commodity_t *)commodity_)->date);
- return ((annotated_commodity_t *)commodity_)->date;
- }
- return 0L;
-}
-
-
-void commodity_base_t::add_price(const datetime_t& date,
- const amount_t& price)
-{
- if (! history)
- history = new history_t;
-
- history_map::iterator i = history->prices.find(date);
- if (i != history->prices.end()) {
- (*i).second = price;
- } else {
- std::pair<history_map::iterator, bool> result
- = history->prices.insert(history_pair(date, price));
- assert(result.second);
- }
-}
-
-bool commodity_base_t::remove_price(const datetime_t& date)
-{
- if (history) {
- history_map::size_type n = history->prices.erase(date);
- if (n > 0) {
- if (history->prices.empty())
- history = NULL;
- return true;
- }
- }
- return false;
-}
-
-commodity_base_t * commodity_base_t::create(const std::string& symbol)
-{
- commodity_base_t * commodity = new commodity_base_t(symbol);
-
- DEBUG_PRINT("amounts.commodities", "Creating base commodity " << symbol);
-
- std::pair<base_commodities_map::iterator, bool> result
- = commodities.insert(base_commodities_pair(symbol, commodity));
- assert(result.second);
-
- return commodity;
-}
-
-bool commodity_t::needs_quotes(const std::string& symbol)
-{
- for (const char * p = symbol.c_str(); *p; p++)
- if (std::isspace(*p) || std::isdigit(*p) || *p == '-' || *p == '.')
- return true;
-
- return false;
-}
-
-bool commodity_t::valid() const
-{
- if (symbol().empty() && this != null_commodity) {
- DEBUG_PRINT("ledger.validate",
- "commodity_t: symbol().empty() && this != null_commodity");
- return false;
- }
-
- if (annotated && ! base) {
- DEBUG_PRINT("ledger.validate", "commodity_t: annotated && ! base");
- return false;
- }
-
- if (precision() > 16) {
- DEBUG_PRINT("ledger.validate", "commodity_t: precision() > 16");
- return false;
- }
-
- return true;
-}
-
-commodity_t * commodity_t::create(const std::string& symbol)
-{
- std::auto_ptr<commodity_t> commodity(new commodity_t);
-
- commodity->base = commodity_base_t::create(symbol);
-
- if (needs_quotes(symbol)) {
- commodity->qualified_symbol = "\"";
- commodity->qualified_symbol += symbol;
- commodity->qualified_symbol += "\"";
- } else {
- commodity->qualified_symbol = symbol;
- }
-
- DEBUG_PRINT("amounts.commodities",
- "Creating commodity " << commodity->qualified_symbol);
-
- std::pair<commodities_map::iterator, bool> result
- = commodities.insert(commodities_pair(symbol, commodity.get()));
- if (! result.second)
- return NULL;
-
- // Start out the new commodity with the default commodity's flags
- // and precision, if one has been defined.
- if (default_commodity)
- commodity->drop_flags(COMMODITY_STYLE_THOUSANDS |
- COMMODITY_STYLE_NOMARKET);
-
- return commodity.release();
-}
-
-commodity_t * commodity_t::find_or_create(const std::string& symbol)
-{
- DEBUG_PRINT("amounts.commodities", "Find-or-create commodity " << symbol);
-
- commodity_t * commodity = find(symbol);
- if (commodity)
- return commodity;
- return create(symbol);
-}
-
-commodity_t * commodity_t::find(const std::string& symbol)
-{
- DEBUG_PRINT("amounts.commodities", "Find commodity " << symbol);
-
- commodities_map::const_iterator i = commodities.find(symbol);
- if (i != commodities.end())
- return (*i).second;
- return NULL;
-}
-
-amount_t commodity_base_t::value(const datetime_t& moment)
-{
- datetime_t age;
- amount_t price;
-
- if (history) {
- assert(history->prices.size() > 0);
-
- if (! moment) {
- history_map::reverse_iterator r = history->prices.rbegin();
- age = (*r).first;
- price = (*r).second;
- } else {
- history_map::iterator i = history->prices.lower_bound(moment);
- if (i == history->prices.end()) {
- history_map::reverse_iterator r = history->prices.rbegin();
- age = (*r).first;
- price = (*r).second;
- } else {
- age = (*i).first;
- if (moment != age) {
- if (i != history->prices.begin()) {
- --i;
- age = (*i).first;
- price = (*i).second;
- } else {
- age = 0;
- }
- } else {
- price = (*i).second;
- }
- }
- }
- }
-
- if (updater && ! (flags & COMMODITY_STYLE_NOMARKET))
- (*updater)(*this, moment, age,
- (history && history->prices.size() > 0 ?
- (*history->prices.rbegin()).first : datetime_t()), price);
-
- return price;
-}
-
-bool annotated_commodity_t::operator==(const commodity_t& comm) const
-{
- // If the base commodities don't match, the game's up.
- if (base != comm.base)
- return false;
-
- if (price &&
- (! comm.annotated ||
- price != static_cast<const annotated_commodity_t&>(comm).price))
- return false;
-
- if (date &&
- (! comm.annotated ||
- date != static_cast<const annotated_commodity_t&>(comm).date))
- return false;
-
- if (! tag.empty() &&
- (! comm.annotated ||
- tag != static_cast<const annotated_commodity_t&>(comm).tag))
- return false;
-
- return true;
-}
-
-void
-annotated_commodity_t::write_annotations(std::ostream& out,
- const amount_t& price,
- const datetime_t& date,
- const std::string& tag)
-{
- if (price)
- out << " {" << price << '}';
-
- if (date)
- out << " [" << date_t(date) << ']';
-
- if (! tag.empty())
- out << " (" << tag << ')';
-}
-
-commodity_t *
-annotated_commodity_t::create(const commodity_t& comm,
- const amount_t& price,
- const datetime_t& date,
- const std::string& tag,
- const std::string& mapping_key)
-{
- std::auto_ptr<annotated_commodity_t> commodity(new annotated_commodity_t);
-
- // Set the annotated bits
- commodity->price = price;
- commodity->date = date;
- commodity->tag = tag;
-
- commodity->ptr = &comm;
- assert(commodity->ptr);
- commodity->base = comm.base;
- assert(commodity->base);
-
- commodity->qualified_symbol = comm.symbol();
-
- DEBUG_PRINT("amounts.commodities", "Creating annotated commodity "
- << "symbol " << commodity->symbol()
- << " key " << mapping_key << std::endl
- << " price " << price << " "
- << " date " << date << " "
- << " tag " << tag);
-
- // Add the fully annotated name to the map, so that this symbol may
- // quickly be found again.
- std::pair<commodities_map::iterator, bool> result
- = commodities.insert(commodities_pair(mapping_key, commodity.get()));
- if (! result.second)
- return NULL;
-
- return commodity.release();
-}
-
-namespace {
- std::string make_qualified_name(const commodity_t& comm,
- const amount_t& price,
- const datetime_t& date,
- const std::string& tag)
- {
- if (price < 0)
- throw new amount_error("A commodity's price may not be negative");
-
- std::ostringstream name;
-
- comm.write(name);
- annotated_commodity_t::write_annotations(name, price, date, tag);
-
- DEBUG_PRINT("amounts.commodities", "make_qualified_name for "
- << comm.qualified_symbol << std::endl
- << " price " << price << " "
- << " date " << date << " "
- << " tag " << tag);
-
- DEBUG_PRINT("amounts.commodities", "qualified_name is " << name.str());
-
- return name.str();
- }
-}
-
-commodity_t *
-annotated_commodity_t::find_or_create(const commodity_t& comm,
- const amount_t& price,
- const datetime_t& date,
- const std::string& tag)
-{
- std::string name = make_qualified_name(comm, price, date, tag);
-
- commodity_t * ann_comm = commodity_t::find(name);
- if (ann_comm) {
- assert(ann_comm->annotated);
- return ann_comm;
- }
- return create(comm, price, date, tag, name);
-}
-
-bool compare_amount_commodities::operator()(const amount_t * left,
- const amount_t * right) const
-{
- commodity_t& leftcomm(left->commodity());
- commodity_t& rightcomm(right->commodity());
-
- int cmp = leftcomm.base_symbol().compare(rightcomm.base_symbol());
- if (cmp != 0)
- return cmp < 0;
-
- if (! leftcomm.annotated) {
- assert(rightcomm.annotated);
- return true;
- }
- else if (! rightcomm.annotated) {
- assert(leftcomm.annotated);
- return false;
- }
- else {
- annotated_commodity_t& aleftcomm(static_cast<annotated_commodity_t&>(leftcomm));
- annotated_commodity_t& arightcomm(static_cast<annotated_commodity_t&>(rightcomm));
-
- if (! aleftcomm.price && arightcomm.price)
- return true;
- if (aleftcomm.price && ! arightcomm.price)
- return false;
-
- if (aleftcomm.price && arightcomm.price) {
- amount_t leftprice(aleftcomm.price);
- leftprice.reduce();
- amount_t rightprice(arightcomm.price);
- rightprice.reduce();
-
- if (leftprice.commodity() == rightprice.commodity()) {
- int diff = leftprice.compare(rightprice);
- if (diff)
- return diff;
- } else {
- // Since we have two different amounts, there's really no way
- // to establish a true sorting order; we'll just do it based
- // on the numerical values.
- leftprice.clear_commodity();
- rightprice.clear_commodity();
-
- int diff = leftprice.compare(rightprice);
- if (diff)
- return diff;
- }
- }
-
- if (! aleftcomm.date && arightcomm.date)
- return true;
- if (aleftcomm.date && ! arightcomm.date)
- return false;
-
- if (aleftcomm.date && arightcomm.date) {
- int diff = aleftcomm.date - arightcomm.date;
- if (diff)
- return diff < 0;
- }
-
- if (aleftcomm.tag.empty() && ! arightcomm.tag.empty())
- return true;
- if (! aleftcomm.tag.empty() && arightcomm.tag.empty())
- return false;
-
- if (! aleftcomm.tag.empty() && ! arightcomm.tag.empty())
- return aleftcomm.tag < arightcomm.tag;
-
- // The two annotated commodities don't differ enough to matter. This
- // should make this identical.
- return true;
- }
-}
-
-} // namespace ledger
-
-#ifdef USE_BOOST_PYTHON
-
-#include <boost/python.hpp>
-#include <Python.h>
-
-using namespace boost::python;
-using namespace ledger;
-
-int py_amount_quantity(amount_t& amount)
-{
- std::string quant = amount.quantity_string();
- return std::atol(quant.c_str());
-}
-
-void py_parse_1(amount_t& amount, const std::string& str,
- unsigned char flags) {
- amount.parse(str, flags);
-}
-void py_parse_2(amount_t& amount, const std::string& str) {
- amount.parse(str);
-}
-
-struct commodity_updater_wrap : public commodity_base_t::updater_t
-{
- PyObject * self;
- commodity_updater_wrap(PyObject * self_) : self(self_) {}
-
- virtual void operator()(commodity_base_t& commodity,
- const datetime_t& moment,
- const datetime_t& date,
- const datetime_t& last,
- amount_t& price) {
- call_method<void>(self, "__call__", commodity, moment, date, last, price);
- }
-};
-
-commodity_t * py_find_commodity(const std::string& symbol)
-{
- return commodity_t::find(symbol);
-}
-
-#define EXC_TRANSLATOR(type) \
- void exc_translate_ ## type(const type& err) { \
- PyErr_SetString(PyExc_RuntimeError, err.what()); \
- }
-
-EXC_TRANSLATOR(amount_error)
-
-void export_amount()
-{
- scope().attr("AMOUNT_PARSE_NO_MIGRATE") = AMOUNT_PARSE_NO_MIGRATE;
- scope().attr("AMOUNT_PARSE_NO_REDUCE") = AMOUNT_PARSE_NO_REDUCE;
-
- class_< amount_t > ("Amount")
- .def(init<amount_t>())
- .def(init<std::string>())
- .def(init<char *>())
- .def(init<bool>())
- .def(init<long>())
- .def(init<unsigned long>())
- .def(init<double>())
-
- .def(self += self)
- .def(self += long())
- .def(self + self)
- .def(self + long())
- .def(self -= self)
- .def(self -= long())
- .def(self - self)
- .def(self - long())
- .def(self *= self)
- .def(self *= long())
- .def(self * self)
- .def(self * long())
- .def(self /= self)
- .def(self /= long())
- .def(self / self)
- .def(self / long())
- .def(- self)
-
- .def(self < self)
- .def(self < long())
- .def(self <= self)
- .def(self <= long())
- .def(self > self)
- .def(self > long())
- .def(self >= self)
- .def(self >= long())
- .def(self == self)
- .def(self == long())
- .def(self != self)
- .def(self != long())
- .def(! self)
-
- .def(self_ns::int_(self))
- .def(self_ns::float_(self))
- .def(self_ns::str(self))
- .def(abs(self))
-
- .add_property("commodity",
- make_function(&amount_t::commodity,
- return_value_policy<reference_existing_object>()),
- make_function(&amount_t::set_commodity,
- with_custodian_and_ward<1, 2>()))
-
- .def("strip_annotations", &amount_t::strip_annotations)
-
- .def("negate", &amount_t::negate)
- .def("negated", &amount_t::negated)
- .def("parse", py_parse_1)
- .def("parse", py_parse_2)
- .def("reduce", &amount_t::reduce)
-
- .def("valid", &amount_t::valid)
- ;
-
- class_< commodity_base_t::updater_t, commodity_updater_wrap,
- boost::noncopyable >
- ("Updater")
- ;
-
- scope().attr("COMMODITY_STYLE_DEFAULTS") = COMMODITY_STYLE_DEFAULTS;
- scope().attr("COMMODITY_STYLE_SUFFIXED") = COMMODITY_STYLE_SUFFIXED;
- scope().attr("COMMODITY_STYLE_SEPARATED") = COMMODITY_STYLE_SEPARATED;
- scope().attr("COMMODITY_STYLE_EUROPEAN") = COMMODITY_STYLE_EUROPEAN;
- scope().attr("COMMODITY_STYLE_THOUSANDS") = COMMODITY_STYLE_THOUSANDS;
- scope().attr("COMMODITY_STYLE_NOMARKET") = COMMODITY_STYLE_NOMARKET;
- scope().attr("COMMODITY_STYLE_BUILTIN") = COMMODITY_STYLE_BUILTIN;
-
- class_< commodity_t > ("Commodity")
- .add_property("symbol", &commodity_t::symbol)
-
-#if 0
- .add_property("name", &commodity_t::name, &commodity_t::set_name)
- .add_property("note", &commodity_t::note, &commodity_t::set_note)
- .add_property("precision", &commodity_t::precision,
- &commodity_t::set_precision)
- .add_property("flags", &commodity_t::flags, &commodity_t::set_flags)
- .add_property("add_flags", &commodity_t::add_flags)
- .add_property("drop_flags", &commodity_t::drop_flags)
-#if 0
- .add_property("updater", &commodity_t::updater)
-#endif
-
- .add_property("smaller",
- make_getter(&commodity_t::smaller,
- return_value_policy<reference_existing_object>()),
- make_setter(&commodity_t::smaller,
- return_value_policy<reference_existing_object>()))
- .add_property("larger",
- make_getter(&commodity_t::larger,
- return_value_policy<reference_existing_object>()),
- make_setter(&commodity_t::larger,
- return_value_policy<reference_existing_object>()))
-
- .def(self_ns::str(self))
-
- .def("find", py_find_commodity,
- return_value_policy<reference_existing_object>())
- .staticmethod("find")
-#endif
-
- .def("add_price", &commodity_t::add_price)
- .def("remove_price", &commodity_t::remove_price)
- .def("value", &commodity_t::value)
-
- .def("valid", &commodity_t::valid)
- ;
-
-#define EXC_TRANSLATE(type) \
- register_exception_translator<type>(&exc_translate_ ## type);
-
- EXC_TRANSLATE(amount_error);
-}
-
-#endif // USE_BOOST_PYTHON
diff --git a/amount.h b/amount.h
deleted file mode 100644
index ef1d2a3d..00000000
--- a/amount.h
+++ /dev/null
@@ -1,631 +0,0 @@
-#ifndef _AMOUNT_H
-#define _AMOUNT_H
-
-#include <map>
-#include <stack>
-#include <string>
-#include <memory>
-#include <cctype>
-#include <iostream>
-#include <sstream>
-#include <cassert>
-#include <exception>
-
-#include "datetime.h"
-#include "debug.h"
-#include "error.h"
-
-namespace ledger {
-
-extern bool do_cleanup;
-
-class commodity_t;
-
-class amount_t
-{
- public:
- class bigint_t;
-
- static bool keep_price;
- static bool keep_date;
- static bool keep_tag;
- static bool keep_base;
-
- protected:
- void _init();
- void _copy(const amount_t& amt);
- void _release();
- void _dup();
- void _resize(unsigned int prec);
-
- void _clear() {
- if (quantity) {
- assert(commodity_);
- _release();
- quantity = NULL;
- commodity_ = NULL;
- } else {
- assert(! commodity_);
- }
- }
-
- bigint_t * quantity;
- commodity_t * commodity_;
-
- public:
- // constructors
- amount_t() : quantity(NULL), commodity_(NULL) {}
- amount_t(const amount_t& amt) : quantity(NULL) {
- if (amt.quantity)
- _copy(amt);
- else
- commodity_ = NULL;
- }
- amount_t(const std::string& value) : quantity(NULL) {
- parse(value);
- }
- amount_t(const char * value) : quantity(NULL) {
- parse(value);
- }
- amount_t(const bool value);
- amount_t(const long value);
- amount_t(const unsigned long value);
- amount_t(const double value);
-
- // destructor
- ~amount_t() {
- if (quantity)
- _release();
- }
-
- commodity_t& commodity() const;
- void set_commodity(commodity_t& comm) {
- commodity_ = &comm;
- }
- void annotate_commodity(const amount_t& price,
- const datetime_t& date = datetime_t(),
- const std::string& tag = "");
- amount_t strip_annotations(const bool _keep_price = keep_price,
- const bool _keep_date = keep_date,
- const bool _keep_tag = keep_tag) const;
- void clear_commodity() {
- commodity_ = NULL;
- }
- amount_t price() const;
- datetime_t date() const;
-
- bool null() const {
- return ! quantity && ! commodity_;
- }
-
- std::string quantity_string() const;
-
- // assignment operator
- amount_t& operator=(const amount_t& amt);
- amount_t& operator=(const std::string& value);
- amount_t& operator=(const char * value);
- amount_t& operator=(const bool value);
- amount_t& operator=(const long value);
- amount_t& operator=(const unsigned long value);
- amount_t& operator=(const double value);
-
- // general methods
- amount_t round(unsigned int prec) const;
- amount_t round() const;
- amount_t unround() const;
-
- // in-place arithmetic
- amount_t& operator+=(const amount_t& amt);
- amount_t& operator-=(const amount_t& amt);
- amount_t& operator*=(const amount_t& amt);
- amount_t& operator/=(const amount_t& amt);
-
- template <typename T>
- amount_t& operator+=(T value) {
- return *this += amount_t(value);
- }
- template <typename T>
- amount_t& operator-=(T value) {
- return *this -= amount_t(value);
- }
- template <typename T>
- amount_t& operator*=(T value) {
- return *this *= amount_t(value);
- }
- template <typename T>
- amount_t& operator/=(T value) {
- return *this /= amount_t(value);
- }
-
- // simple arithmetic
- amount_t operator+(const amount_t& amt) const {
- amount_t temp = *this;
- temp += amt;
- return temp;
- }
- amount_t operator-(const amount_t& amt) const {
- amount_t temp = *this;
- temp -= amt;
- return temp;
- }
- amount_t operator*(const amount_t& amt) const {
- amount_t temp = *this;
- temp *= amt;
- return temp;
- }
- amount_t operator/(const amount_t& amt) const {
- amount_t temp = *this;
- temp /= amt;
- return temp;
- }
-
- template <typename T>
- amount_t operator+(T value) const {
- amount_t temp = *this;
- temp += value;
- return temp;
- }
- template <typename T>
- amount_t operator-(T value) const {
- amount_t temp = *this;
- temp -= value;
- return temp;
- }
- template <typename T>
- amount_t operator*(T value) const {
- amount_t temp = *this;
- temp *= value;
- return temp;
- }
- template <typename T>
- amount_t operator/(T value) const {
- amount_t temp = *this;
- temp /= value;
- return temp;
- }
-
- // unary negation
- void negate();
- amount_t negated() const {
- amount_t temp = *this;
- temp.negate();
- return temp;
- }
- amount_t operator-() const {
- return negated();
- }
-
- // test for non-zero (use ! for zero)
- operator bool() const;
- operator long() const;
- operator double() const;
-
- bool realzero() const;
-
- // comparisons between amounts
- int compare(const amount_t& amt) const;
-
- bool operator<(const amount_t& amt) const {
- return compare(amt) < 0;
- }
- bool operator<=(const amount_t& amt) const {
- return compare(amt) <= 0;
- }
- bool operator>(const amount_t& amt) const {
- return compare(amt) > 0;
- }
- bool operator>=(const amount_t& amt) const {
- return compare(amt) >= 0;
- }
- bool operator==(const amount_t& amt) const;
- bool operator!=(const amount_t& amt) const;
-
- template <typename T>
- void parse_num(T num) {
- std::ostringstream temp;
- temp << num;
- std::istringstream in(temp.str());
- parse(in);
- }
-
- int sign() const;
-
- // POD comparisons
-#define AMOUNT_CMP_INT(OP) \
- template <typename T> \
- bool operator OP (T num) const { \
- if (num == 0) { \
- return sign() OP 0; \
- } else { \
- amount_t amt; \
- amt.parse_num(num); \
- return *this OP amt; \
- } \
- }
-
- AMOUNT_CMP_INT(<)
- AMOUNT_CMP_INT(<=)
- AMOUNT_CMP_INT(>)
- AMOUNT_CMP_INT(>=)
- AMOUNT_CMP_INT(==)
-
- template <typename T>
- bool operator!=(T num) const {
- return ! (*this == num);
- }
-
- amount_t value(const datetime_t& moment) const;
-
- void abs() {
- if (*this < 0)
- negate();
- }
-
-#define AMOUNT_PARSE_NO_MIGRATE 0x01
-#define AMOUNT_PARSE_NO_REDUCE 0x02
-#define AMOUNT_PARSE_SOFT_FAIL 0x04
-
- bool parse(std::istream& in, unsigned char flags = 0);
- bool parse(const std::string& str, unsigned char flags = 0);
- void reduce();
-
- amount_t reduced() const {
- amount_t temp(*this);
- temp.reduce();
- return temp;
- }
-
- void read_quantity(char *& data);
- void read_quantity(std::istream& in);
- void write_quantity(std::ostream& out) const;
-
- bool valid() const;
-
- // Classes that are friends, and help to implement this class
-
- friend std::ostream& operator<<(std::ostream& out, const amount_t& amt);
- friend std::istream& operator>>(std::istream& in, amount_t& amt);
-
- friend unsigned int sizeof_bigint_t();
-
- friend void read_binary_amount(char *& data, amount_t& amt);
- friend void write_binary_amount(std::ostream& out, const amount_t& amt);
-
- // This function is special, and exists only to support a custom
- // optimization in binary.cc (which offers a significant enough gain
- // to be worth the trouble).
-
- friend void clean_commodity_history(char * item_pool,
- char * item_pool_end);
-
- friend void parse_annotations(std::istream& in, amount_t& price,
- datetime_t& date, std::string& tag);
-};
-
-unsigned int sizeof_bigint_t();
-
-void parse_quantity(std::istream& in, std::string& value);
-void parse_commodity(std::istream& in, std::string& symbol);
-void parse_annotations(std::istream& in, const std::string& symbol,
- std::string& name, std::string& price,
- std::string& date, std::string& tag);
-void parse_conversion(const std::string& larger,
- const std::string& smaller);
-
-inline bool is_quote_or_paren(char * p) {
- return *p == '"' || *p == '{' || *p == '[' || *p == '(';
-}
-
-inline char * scan_past_quotes_and_parens(char * expr)
-{
- std::stack<char> paren_stack;
-
- char * p;
- for (p = expr; *p; p++) {
- if (*p == '"' ||
- ((*p == '(' || ((*p == '{' || *p == '[') &&
- paren_stack.top() != '(')) &&
- paren_stack.top() != '"')) {
- paren_stack.push(*p);
- }
- else if ((*p == ')' && paren_stack.top() == '(') ||
- (*p == '}' && paren_stack.top() == '{') ||
- (*p == ']' && paren_stack.top() == '[') ||
- (*p == '"' && paren_stack.top() == '"')) {
- paren_stack.pop();
- if (paren_stack.size() == 0)
- break;
- }
- }
- return p;
-}
-
-inline amount_t abs(const amount_t& amt) {
- return amt < 0 ? amt.negated() : amt;
-}
-
-std::ostream& operator<<(std::ostream& out, const amount_t& amt);
-
-inline std::istream& operator>>(std::istream& in, amount_t& amt) {
- amt.parse(in);
- return in;
-}
-
-
-#define COMMODITY_STYLE_DEFAULTS 0x0000
-#define COMMODITY_STYLE_SUFFIXED 0x0001
-#define COMMODITY_STYLE_SEPARATED 0x0002
-#define COMMODITY_STYLE_EUROPEAN 0x0004
-#define COMMODITY_STYLE_THOUSANDS 0x0008
-#define COMMODITY_STYLE_NOMARKET 0x0010
-#define COMMODITY_STYLE_BUILTIN 0x0020
-
-typedef std::map<const datetime_t, amount_t> history_map;
-typedef std::pair<const datetime_t, amount_t> history_pair;
-
-class commodity_base_t;
-
-typedef std::map<const std::string, commodity_base_t *> base_commodities_map;
-typedef std::pair<const std::string, commodity_base_t *> base_commodities_pair;
-
-class commodity_base_t
-{
- public:
- friend class commodity_t;
- friend class annotated_commodity_t;
-
- typedef unsigned long ident_t;
-
- ident_t ident;
- std::string name;
- std::string note;
- unsigned char precision;
- unsigned char flags;
- amount_t * smaller;
- amount_t * larger;
-
- commodity_base_t()
- : precision(0), flags(COMMODITY_STYLE_DEFAULTS),
- smaller(NULL), larger(NULL), history(NULL) {}
-
- commodity_base_t(const std::string& _symbol,
- unsigned int _precision = 0,
- unsigned int _flags = COMMODITY_STYLE_DEFAULTS)
- : precision(_precision), flags(_flags),
- smaller(NULL), larger(NULL), symbol(_symbol), history(NULL) {}
-
- ~commodity_base_t() {
- if (history) delete history;
- if (smaller) delete smaller;
- if (larger) delete larger;
- }
-
- static base_commodities_map commodities;
- static commodity_base_t * create(const std::string& symbol);
-
- std::string symbol;
-
- struct history_t {
- history_map prices;
- datetime_t last_lookup;
- datetime_t bogus_time;
- history_t() : last_lookup(0), bogus_time(0) {}
- };
- history_t * history;
-
- void add_price(const datetime_t& date, const amount_t& price);
- bool remove_price(const datetime_t& date);
- amount_t value(const datetime_t& moment = datetime_t::now);
-
- class updater_t {
- public:
- virtual ~updater_t() {}
- virtual void operator()(commodity_base_t& commodity,
- const datetime_t& moment,
- const datetime_t& date,
- const datetime_t& last,
- amount_t& price) = 0;
- };
- friend class updater_t;
-
- static updater_t * updater;
-};
-
-typedef std::map<const std::string, commodity_t *> commodities_map;
-typedef std::pair<const std::string, commodity_t *> commodities_pair;
-
-class commodity_t
-{
- friend class annotated_commodity_t;
-
- public:
- // This map remembers all commodities that have been defined.
-
- static commodities_map commodities;
- static bool commodities_sorted;
- static commodity_t * null_commodity;
- static commodity_t * default_commodity;
-
- static commodity_t * create(const std::string& symbol);
- static commodity_t * find(const std::string& name);
- static commodity_t * find_or_create(const std::string& symbol);
-
- static bool needs_quotes(const std::string& symbol);
-
- static void make_alias(const std::string& symbol,
- commodity_t * commodity);
-
- // These are specific to each commodity reference
-
- typedef unsigned long ident_t;
-
- ident_t ident;
- commodity_base_t * base;
- std::string qualified_symbol;
- bool annotated;
-
- public:
- explicit commodity_t() : base(NULL), annotated(false) {}
- virtual ~commodity_t() {}
-
- operator bool() const {
- return this != null_commodity;
- }
- virtual bool operator==(const commodity_t& comm) const {
- if (comm.annotated)
- return comm == *this;
- return base == comm.base;
- }
- bool operator!=(const commodity_t& comm) const {
- return ! (*this == comm);
- }
-
- std::string base_symbol() const {
- return base->symbol;
- }
- std::string symbol() const {
- return qualified_symbol;
- }
-
- void write(std::ostream& out) const {
- out << symbol();
- }
-
- std::string name() const {
- return base->name;
- }
- void set_name(const std::string& arg) {
- base->name = arg;
- }
-
- std::string note() const {
- return base->note;
- }
- void set_note(const std::string& arg) {
- base->note = arg;
- }
-
- unsigned char precision() const {
- return base->precision;
- }
- void set_precision(unsigned char arg) {
- base->precision = arg;
- }
-
- unsigned char flags() const {
- return base->flags;
- }
- void set_flags(unsigned char arg) {
- base->flags = arg;
- }
- void add_flags(unsigned char arg) {
- base->flags |= arg;
- }
- void drop_flags(unsigned char arg) {
- base->flags &= ~arg;
- }
-
- amount_t * smaller() const {
- return base->smaller;
- }
- void set_smaller(const amount_t& arg) {
- if (base->smaller)
- delete base->smaller;
- base->smaller = new amount_t(arg);
- }
-
- amount_t * larger() const {
- return base->larger;
- }
- void set_larger(const amount_t& arg) {
- if (base->larger)
- delete base->larger;
- base->larger = new amount_t(arg);
- }
-
- commodity_base_t::history_t * history() const {
- return base->history;
- }
-
- void add_price(const datetime_t& date, const amount_t& price) {
- return base->add_price(date, price);
- }
- bool remove_price(const datetime_t& date) {
- return base->remove_price(date);
- }
- amount_t value(const datetime_t& moment = datetime_t::now) const {
- return base->value(moment);
- }
-
- bool valid() const;
-};
-
-class annotated_commodity_t : public commodity_t
-{
- public:
- const commodity_t * ptr;
-
- amount_t price;
- datetime_t date;
- std::string tag;
-
- explicit annotated_commodity_t() {
- annotated = true;
- }
-
- virtual bool operator==(const commodity_t& comm) const;
-
- void write_annotations(std::ostream& out) const {
- annotated_commodity_t::write_annotations(out, price, date, tag);
- }
-
- static void write_annotations(std::ostream& out,
- const amount_t& price,
- const datetime_t& date,
- const std::string& tag);
-
- private:
- static commodity_t * create(const commodity_t& comm,
- const amount_t& price,
- const datetime_t& date,
- const std::string& tag,
- const std::string& mapping_key);
-
- static commodity_t * find_or_create(const commodity_t& comm,
- const amount_t& price,
- const datetime_t& date,
- const std::string& tag);
-
- friend class amount_t;
-};
-
-inline std::ostream& operator<<(std::ostream& out,
- const commodity_t& comm) {
- out << comm.symbol();
- return out;
-}
-
-inline amount_t amount_t::round() const {
- return round(commodity().precision());
-}
-
-inline commodity_t& amount_t::commodity() const {
- if (! commodity_)
- return *commodity_t::null_commodity;
- else
- return *commodity_;
-}
-
-class amount_error : public error {
- public:
- amount_error(const std::string& reason) throw() : error(reason) {}
- virtual ~amount_error() throw() {}
-};
-
-struct compare_amount_commodities {
- bool operator()(const amount_t * left, const amount_t * right) const;
-};
-
-} // namespace ledger
-
-#endif // _AMOUNT_H
diff --git a/amounts.cc b/amounts.cc
deleted file mode 100644
index 6bb9ddbc..00000000
--- a/amounts.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <boost/python.hpp>
-
-using namespace boost::python;
-
-void export_amount();
-void export_balance();
-void export_value();
-
-BOOST_PYTHON_MODULE(amounts)
-{
- export_amount();
- export_balance();
- export_value();
-}
diff --git a/balance.cc b/balance.cc
deleted file mode 100644
index 9e516736..00000000
--- a/balance.cc
+++ /dev/null
@@ -1,529 +0,0 @@
-#include "balance.h"
-#include "util.h"
-
-#include <deque>
-#include <algorithm>
-
-namespace ledger {
-
-amount_t balance_t::amount(const commodity_t& commodity) const
-{
- if (! commodity) {
- if (amounts.size() == 1) {
- amounts_map::const_iterator i = amounts.begin();
- return (*i).second;
- }
- else if (amounts.size() > 1) {
- // Try stripping annotations before giving an error.
- balance_t temp(strip_annotations());
- if (temp.amounts.size() == 1)
- return temp.amount(commodity);
-
- std::ostringstream errmsg;
- errmsg << "Requested amount of a balance with multiple commodities: "
- << temp;
- throw new amount_error(errmsg.str());
- }
- }
- else if (amounts.size() > 0) {
- amounts_map::const_iterator i = amounts.find(&commodity);
- if (i != amounts.end())
- return (*i).second;
- }
- return amount_t();
-}
-
-balance_t balance_t::value(const datetime_t& moment) const
-{
- balance_t temp;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- temp += (*i).second.value(moment);
-
- return temp;
-}
-
-balance_t balance_t::price() const
-{
- balance_t temp;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- temp += (*i).second.price();
-
- return temp;
-}
-
-datetime_t balance_t::date() const
-{
- datetime_t temp;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++) {
- datetime_t date = (*i).second.date();
- if (! temp && date)
- temp = date;
- else if (temp != date)
- return datetime_t();
- }
-
- return temp;
-}
-
-balance_t balance_t::strip_annotations(const bool keep_price,
- const bool keep_date,
- const bool keep_tag) const
-{
- balance_t temp;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- temp += (*i).second.strip_annotations(keep_price, keep_date, keep_tag);
-
- return temp;
-}
-
-void balance_t::write(std::ostream& out,
- const int first_width,
- const int latter_width) const
-{
- bool first = true;
- int lwidth = latter_width;
-
- if (lwidth == -1)
- lwidth = first_width;
-
- if (commodity_t::commodities_sorted) {
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++) {
- int width;
- if (! first) {
- out << std::endl;
- width = lwidth;
- } else {
- first = false;
- width = first_width;
- }
-
- out.width(width);
- out.fill(' ');
- out << std::right << (*i).second;
- }
- } else {
- typedef std::deque<const amount_t *> amounts_deque;
- amounts_deque sorted;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second)
- sorted.push_back(&(*i).second);
-
- std::stable_sort(sorted.begin(), sorted.end(), compare_amount_commodities());
-
- for (amounts_deque::const_iterator i = sorted.begin();
- i != sorted.end();
- i++) {
- int width;
- if (! first) {
- out << std::endl;
- width = lwidth;
- } else {
- first = false;
- width = first_width;
- }
-
- out.width(width);
- out.fill(' ');
- out << std::right << **i;
- }
- }
-
- if (first) {
- out.width(first_width);
- out.fill(' ');
- out << std::right << "0";
- }
-}
-
-balance_t& balance_t::operator*=(const balance_t& bal)
-{
- if (realzero() || bal.realzero()) {
- return *this = 0L;
- }
- else if (bal.amounts.size() == 1) {
- return *this *= (*bal.amounts.begin()).second;
- }
- else if (amounts.size() == 1) {
- return *this = bal * *this;
- }
- else {
- // Since we would fail with an error at this point otherwise, try
- // stripping annotations to see if we can come up with a
- // reasonable result. The user will not notice any annotations
- // missing (since they are viewing a stripped report anyway), only
- // that some of their value expression may not see any pricing or
- // date data because of this operation.
-
- balance_t temp(bal.strip_annotations());
- if (temp.amounts.size() == 1)
- return *this *= temp;
- temp = strip_annotations();
- if (temp.amounts.size() == 1)
- return *this = bal * temp;
-
- std::ostringstream errmsg;
- errmsg << "Cannot multiply two balances: " << temp << " * " << bal;
- throw new amount_error(errmsg.str());
- }
-}
-
-balance_t& balance_t::operator*=(const amount_t& amt)
-{
- if (realzero() || amt.realzero()) {
- return *this = 0L;
- }
- else if (! amt.commodity()) {
- // Multiplying by the null commodity causes all amounts to be
- // increased by the same factor.
- for (amounts_map::iterator i = amounts.begin();
- i != amounts.end();
- i++)
- (*i).second *= amt;
- }
- else if (amounts.size() == 1) {
- *this = (*amounts.begin()).second * amt;
- }
- else {
- amounts_map::iterator i = amounts.find(&amt.commodity());
- if (i != amounts.end()) {
- (*i).second *= amt;
- } else {
- // Try stripping annotations before giving an error.
- balance_t temp(strip_annotations());
- if (temp.amounts.size() == 1) {
- return *this = (*temp.amounts.begin()).second * amt;
- } else {
- i = temp.amounts.find(&amt.commodity());
- if (i != temp.amounts.end())
- return *this = temp * amt;
- }
-
- std::ostringstream errmsg;
- errmsg << "Attempt to multiply balance by a commodity"
- << " not found in that balance: "
- << temp << " * " << amt;
- throw new amount_error(errmsg.str());
- }
- }
- return *this;
-}
-
-balance_t& balance_t::operator/=(const balance_t& bal)
-{
- if (bal.realzero()) {
- std::ostringstream errmsg;
- errmsg << "Attempt to divide by zero: " << *this << " / " << bal;
- throw new amount_error(errmsg.str());
- }
- else if (realzero()) {
- return *this = 0L;
- }
- else if (bal.amounts.size() == 1) {
- return *this /= (*bal.amounts.begin()).second;
- }
- else if (*this == bal) {
- return *this = 1L;
- }
- else {
- // Try stripping annotations before giving an error.
- balance_t temp(bal.strip_annotations());
- if (temp.amounts.size() == 1)
- return *this /= temp;
-
- std::ostringstream errmsg;
- errmsg << "Cannot divide between two balances: " << temp << " / " << bal;
- throw new amount_error(errmsg.str());
- }
-}
-
-balance_t& balance_t::operator/=(const amount_t& amt)
-{
- if (amt.realzero()) {
- std::ostringstream errmsg;
- errmsg << "Attempt to divide by zero: " << *this << " / " << amt;
- throw new amount_error(errmsg.str());
- }
- else if (realzero()) {
- return *this = 0L;
- }
- else if (! amt.commodity()) {
- // Dividing by the null commodity causes all amounts to be
- // decreased by the same factor.
- for (amounts_map::iterator i = amounts.begin();
- i != amounts.end();
- i++)
- (*i).second /= amt;
- }
- else if (amounts.size() == 1 &&
- (*amounts.begin()).first == &amt.commodity()) {
- (*amounts.begin()).second /= amt;
- }
- else {
- amounts_map::iterator i = amounts.find(&amt.commodity());
- if (i != amounts.end()) {
- (*i).second /= amt;
- } else {
- // Try stripping annotations before giving an error.
- balance_t temp(strip_annotations());
- if (temp.amounts.size() == 1 &&
- (*temp.amounts.begin()).first == &amt.commodity())
- return *this = temp / amt;
-
- std::ostringstream errmsg;
- errmsg << "Attempt to divide balance by a commodity"
- << " not found in that balance: "
- << temp << " * " << amt;
- throw new amount_error(errmsg.str());
- }
- }
- return *this;
-}
-
-balance_t::operator amount_t() const
-{
- if (amounts.size() == 1) {
- return (*amounts.begin()).second;
- }
- else if (amounts.size() == 0) {
- return amount_t();
- }
- else {
- // Try stripping annotations before giving an error.
- balance_t temp(strip_annotations());
- if (temp.amounts.size() == 1)
- return (*temp.amounts.begin()).second;
-
- std::ostringstream errmsg;
- errmsg << "Cannot convert a balance with "
- << "multiple commodities to an amount: " << temp;
- throw new amount_error(errmsg.str());
- }
-}
-
-} // namespace ledger
-
-#ifdef USE_BOOST_PYTHON
-
-#include <boost/python.hpp>
-
-using namespace boost::python;
-using namespace ledger;
-
-unsigned int balance_len(balance_t& bal)
-{
- return bal.amounts.size();
-}
-
-amount_t balance_getitem(balance_t& bal, int i)
-{
- std::size_t len = bal.amounts.size();
-
- if (abs(i) >= len) {
- PyErr_SetString(PyExc_IndexError, "Index out of range");
- throw_error_already_set();
- }
-
- int x = i < 0 ? len + i : i;
- amounts_map::iterator elem = bal.amounts.begin();
- while (--x >= 0)
- elem++;
-
- return (*elem).second;
-}
-
-unsigned int balance_pair_len(balance_pair_t& bal_pair)
-{
- return balance_len(bal_pair.quantity);
-}
-
-amount_t balance_pair_getitem(balance_pair_t& bal_pair, int i)
-{
- return balance_getitem(bal_pair.quantity, i);
-}
-
-void export_balance()
-{
- class_< balance_t > ("Balance")
- .def(init<balance_t>())
- .def(init<amount_t>())
- .def(init<long>())
- .def(init<unsigned long>())
- .def(init<double>())
-
- .def(self += self)
- .def(self += other<amount_t>())
- .def(self += long())
- .def(self + self)
- .def(self + other<amount_t>())
- .def(self + long())
- .def(self -= self)
- .def(self -= other<amount_t>())
- .def(self -= long())
- .def(self - self)
- .def(self - other<amount_t>())
- .def(self - long())
- .def(self *= self)
- .def(self *= other<amount_t>())
- .def(self *= long())
- .def(self * self)
- .def(self * other<amount_t>())
- .def(self * long())
- .def(self /= self)
- .def(self /= other<amount_t>())
- .def(self /= long())
- .def(self / self)
- .def(self / other<amount_t>())
- .def(self / long())
- .def(- self)
-
- .def(self < self)
- .def(self < other<amount_t>())
- .def(self < long())
- .def(self <= self)
- .def(self <= other<amount_t>())
- .def(self <= long())
- .def(self > self)
- .def(self > other<amount_t>())
- .def(self > long())
- .def(self >= self)
- .def(self >= other<amount_t>())
- .def(self >= long())
- .def(self == self)
- .def(self == other<amount_t>())
- .def(self == long())
- .def(self != self)
- .def(self != other<amount_t>())
- .def(self != long())
- .def(! self)
-
- .def(abs(self))
- .def(self_ns::str(self))
-
- .def("__len__", balance_len)
- .def("__getitem__", balance_getitem)
-
- .def("valid", &balance_t::valid)
-
- .def("realzero", &balance_t::realzero)
- .def("amount", &balance_t::amount)
- .def("value", &balance_t::value)
- .def("price", &balance_t::price)
- .def("date", &balance_t::date)
- .def("strip_annotations", &balance_t::strip_annotations)
- .def("write", &balance_t::write)
- .def("round", &balance_t::round)
- .def("negate", &balance_t::negate)
- .def("negated", &balance_t::negated)
- ;
-
- class_< balance_pair_t > ("BalancePair")
- .def(init<balance_pair_t>())
- .def(init<balance_t>())
- .def(init<amount_t>())
- .def(init<long>())
- .def(init<unsigned long>())
- .def(init<double>())
-
- .def(self += self)
- .def(self += other<balance_t>())
- .def(self += other<amount_t>())
- .def(self += long())
- .def(self + self)
- .def(self + other<balance_t>())
- .def(self + other<amount_t>())
- .def(self + long())
- .def(self -= self)
- .def(self -= other<balance_t>())
- .def(self -= other<amount_t>())
- .def(self -= long())
- .def(self - self)
- .def(self - other<balance_t>())
- .def(self - other<amount_t>())
- .def(self - long())
- .def(self *= self)
- .def(self *= other<balance_t>())
- .def(self *= other<amount_t>())
- .def(self *= long())
- .def(self * self)
- .def(self * other<balance_t>())
- .def(self * other<amount_t>())
- .def(self * long())
- .def(self /= self)
- .def(self /= other<balance_t>())
- .def(self /= other<amount_t>())
- .def(self /= long())
- .def(self / self)
- .def(self / other<balance_t>())
- .def(self / other<amount_t>())
- .def(self / long())
- .def(- self)
-
- .def(self < self)
- .def(self < other<balance_t>())
- .def(self < other<amount_t>())
- .def(self < long())
- .def(self <= self)
- .def(self <= other<balance_t>())
- .def(self <= other<amount_t>())
- .def(self <= long())
- .def(self > self)
- .def(self > other<balance_t>())
- .def(self > other<amount_t>())
- .def(self > long())
- .def(self >= self)
- .def(self >= other<balance_t>())
- .def(self >= other<amount_t>())
- .def(self >= long())
- .def(self == self)
- .def(self == other<balance_t>())
- .def(self == other<amount_t>())
- .def(self == long())
- .def(self != self)
- .def(self != other<balance_t>())
- .def(self != other<amount_t>())
- .def(self != long())
- .def(! self)
-
- .def(abs(self))
- .def(self_ns::str(self))
-
- .def("__len__", balance_pair_len)
- .def("__getitem__", balance_pair_getitem)
-
- .def("valid", &balance_pair_t::valid)
-
- .def("realzero", &balance_pair_t::realzero)
- .def("amount", &balance_pair_t::amount)
- .def("value", &balance_pair_t::value)
- .def("price", &balance_pair_t::price)
- .def("date", &balance_pair_t::date)
- .def("strip_annotations", &balance_pair_t::strip_annotations)
- .def("write", &balance_pair_t::write)
- .def("round", &balance_pair_t::round)
- .def("negate", &balance_pair_t::negate)
- .def("negated", &balance_pair_t::negated)
-
- .add_property("cost",
- make_getter(&balance_pair_t::cost,
- return_value_policy<reference_existing_object>()))
- ;
-}
-
-#endif // USE_BOOST_PYTHON
diff --git a/balance.h b/balance.h
deleted file mode 100644
index 24b1f2dc..00000000
--- a/balance.h
+++ /dev/null
@@ -1,961 +0,0 @@
-#ifndef _BALANCE_H
-#define _BALANCE_H
-
-#include "amount.h"
-
-#include <map>
-#include <iostream>
-
-namespace ledger {
-
-typedef std::map<const commodity_t *, amount_t> amounts_map;
-typedef std::pair<const commodity_t *, amount_t> amounts_pair;
-
-class balance_t
-{
- public:
- amounts_map amounts;
-
- bool valid() const {
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if (! (*i).second.valid())
- return false;
- return true;
- }
-
- // constructors
- balance_t() {}
- balance_t(const balance_t& bal) {
- for (amounts_map::const_iterator i = bal.amounts.begin();
- i != bal.amounts.end();
- i++)
- *this += (*i).second;
- }
- balance_t(const amount_t& amt) {
- if (! amt.realzero())
- amounts.insert(amounts_pair(&amt.commodity(), amt));
- }
- template <typename T>
- balance_t(T value) {
- amount_t amt(value);
- if (! amt.realzero())
- amounts.insert(amounts_pair(&amt.commodity(), amt));
- }
-
- // assignment operator
- balance_t& operator=(const balance_t& bal) {
- if (this != &bal) {
- amounts.clear();
- for (amounts_map::const_iterator i = bal.amounts.begin();
- i != bal.amounts.end();
- i++)
- *this += (*i).second;
- }
- return *this;
- }
- balance_t& operator=(const amount_t& amt) {
- amounts.clear();
- *this += amt;
- return *this;
- }
- template <typename T>
- balance_t& operator=(T value) {
- amounts.clear();
- *this += value;
- return *this;
- }
-
- // in-place arithmetic
- balance_t& operator+=(const balance_t& bal) {
- for (amounts_map::const_iterator i = bal.amounts.begin();
- i != bal.amounts.end();
- i++)
- *this += (*i).second;
- return *this;
- }
- balance_t& operator+=(const amount_t& amt) {
- amounts_map::iterator i = amounts.find(&amt.commodity());
- if (i != amounts.end())
- (*i).second += amt;
- else if (! amt.realzero())
- amounts.insert(amounts_pair(&amt.commodity(), amt));
- return *this;
- }
- template <typename T>
- balance_t& operator+=(T val) {
- return *this += amount_t(val);
- }
- balance_t& operator-=(const balance_t& bal) {
- for (amounts_map::const_iterator i = bal.amounts.begin();
- i != bal.amounts.end();
- i++)
- *this -= (*i).second;
- return *this;
- }
- balance_t& operator-=(const amount_t& amt) {
- amounts_map::iterator i = amounts.find(&amt.commodity());
- if (i != amounts.end()) {
- (*i).second -= amt;
- if ((*i).second.realzero())
- amounts.erase(i);
- }
- else if (! amt.realzero()) {
- amounts.insert(amounts_pair(&amt.commodity(), - amt));
- }
- return *this;
- }
- template <typename T>
- balance_t& operator-=(T val) {
- return *this -= amount_t(val);
- }
-
- // simple arithmetic
- balance_t operator+(const balance_t& bal) const {
- balance_t temp = *this;
- temp += bal;
- return temp;
- }
- balance_t operator+(const amount_t& amt) const {
- balance_t temp = *this;
- temp += amt;
- return temp;
- }
- template <typename T>
- balance_t operator+(T val) const {
- balance_t temp = *this;
- temp += val;
- return temp;
- }
- balance_t operator-(const balance_t& bal) const {
- balance_t temp = *this;
- temp -= bal;
- return temp;
- }
- balance_t operator-(const amount_t& amt) const {
- balance_t temp = *this;
- temp -= amt;
- return temp;
- }
- template <typename T>
- balance_t operator-(T val) const {
- balance_t temp = *this;
- temp -= val;
- return temp;
- }
-
- // multiplication and divide
- balance_t& operator*=(const balance_t& bal);
- balance_t& operator*=(const amount_t& amt);
- template <typename T>
- balance_t& operator*=(T val) {
- return *this *= amount_t(val);
- }
-
- balance_t& operator/=(const balance_t& bal);
- balance_t& operator/=(const amount_t& amt);
- template <typename T>
- balance_t& operator/=(T val) {
- return *this /= amount_t(val);
- }
-
- // multiplication and divide
- balance_t operator*(const balance_t& bal) const {
- balance_t temp = *this;
- temp *= bal;
- return temp;
- }
- balance_t operator*(const amount_t& amt) const {
- balance_t temp = *this;
- temp *= amt;
- return temp;
- }
- template <typename T>
- balance_t operator*(T val) const {
- balance_t temp = *this;
- temp *= val;
- return temp;
- }
- balance_t operator/(const balance_t& bal) const {
- balance_t temp = *this;
- temp /= bal;
- return temp;
- }
- balance_t operator/(const amount_t& amt) const {
- balance_t temp = *this;
- temp /= amt;
- return temp;
- }
- template <typename T>
- balance_t operator/(T val) const {
- balance_t temp = *this;
- temp /= val;
- return temp;
- }
-
- // comparison
- bool operator<(const balance_t& bal) const {
- for (amounts_map::const_iterator i = bal.amounts.begin();
- i != bal.amounts.end();
- i++)
- if (! (amount(*(*i).first) < (*i).second))
- return false;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if (! ((*i).second < bal.amount(*(*i).first)))
- return false;
-
- if (bal.amounts.size() == 0 && amounts.size() == 0)
- return false;
-
- return true;
- }
- bool operator<(const amount_t& amt) const {
- if (amt.commodity())
- return amount(amt.commodity()) < amt;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second < amt)
- return true;
- return false;
- }
- template <typename T>
- bool operator<(T val) const {
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second < val)
- return true;
- return false;
- }
-
- bool operator<=(const balance_t& bal) const {
- for (amounts_map::const_iterator i = bal.amounts.begin();
- i != bal.amounts.end();
- i++)
- if (! (amount(*(*i).first) <= (*i).second))
- return false;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if (! ((*i).second <= bal.amount(*(*i).first)))
- return false;
-
- return true;
- }
- bool operator<=(const amount_t& amt) const {
- if (amt.commodity())
- return amount(amt.commodity()) <= amt;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second <= amt)
- return true;
- return false;
- }
- template <typename T>
- bool operator<=(T val) const {
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second <= val)
- return true;
- return false;
- }
-
- bool operator>(const balance_t& bal) const {
- for (amounts_map::const_iterator i = bal.amounts.begin();
- i != bal.amounts.end();
- i++)
- if (! (amount(*(*i).first) > (*i).second))
- return false;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if (! ((*i).second > bal.amount(*(*i).first)))
- return false;
-
- if (bal.amounts.size() == 0 && amounts.size() == 0)
- return false;
-
- return true;
- }
- bool operator>(const amount_t& amt) const {
- if (amt.commodity())
- return amount(amt.commodity()) > amt;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second > amt)
- return true;
- return false;
- }
- template <typename T>
- bool operator>(T val) const {
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second > val)
- return true;
- return false;
- }
-
- bool operator>=(const balance_t& bal) const {
- for (amounts_map::const_iterator i = bal.amounts.begin();
- i != bal.amounts.end();
- i++)
- if (! (amount(*(*i).first) >= (*i).second))
- return false;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if (! ((*i).second >= bal.amount(*(*i).first)))
- return false;
-
- return true;
- }
- bool operator>=(const amount_t& amt) const {
- if (amt.commodity())
- return amount(amt.commodity()) >= amt;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second >= amt)
- return true;
- return false;
- }
- template <typename T>
- bool operator>=(T val) const {
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second >= val)
- return true;
- return false;
- }
-
- bool operator==(const balance_t& bal) const {
- amounts_map::const_iterator i, j;
- for (i = amounts.begin(), j = bal.amounts.begin();
- i != amounts.end() && j != bal.amounts.end();
- i++, j++) {
- if (! ((*i).first == (*j).first &&
- (*i).second == (*j).second))
- return false;
- }
- return i == amounts.end() && j == bal.amounts.end();
- }
- bool operator==(const amount_t& amt) const {
- if (amt.commodity())
- return amounts.size() == 1 && (*amounts.begin()).second == amt;
-
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second == amt)
- return true;
- return false;
- }
- template <typename T>
- bool operator==(T val) const {
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second == val)
- return true;
- return false;
- }
-
- bool operator!=(const balance_t& bal) const {
- return ! (*this == bal);
- }
- bool operator!=(const amount_t& amt) const {
- return ! (*this == amt);
- }
- template <typename T>
- bool operator!=(T val) const {
- return ! (*this == val);
- }
-
- // unary negation
- void negate() {
- for (amounts_map::iterator i = amounts.begin();
- i != amounts.end();
- i++)
- (*i).second.negate();
- }
- balance_t negated() const {
- balance_t temp = *this;
- temp.negate();
- return temp;
- }
- balance_t operator-() const {
- return negated();
- }
-
- // conversion operators
- operator amount_t() const;
- operator bool() const {
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second)
- return true;
- return false;
- }
-
- bool realzero() const {
- if (amounts.size() == 0)
- return true;
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if (! (*i).second.realzero())
- return false;
- return true;
- }
-
- amount_t amount(const commodity_t& commodity =
- *commodity_t::null_commodity) const;
- balance_t value(const datetime_t& moment = datetime_t::now) const;
- balance_t price() const;
- datetime_t date() const;
-
- balance_t
- strip_annotations(const bool keep_price = amount_t::keep_price,
- const bool keep_date = amount_t::keep_date,
- const bool keep_tag = amount_t::keep_tag) const;
-
- void write(std::ostream& out, const int first_width,
- const int latter_width = -1) const;
-
- void abs() {
- for (amounts_map::iterator i = amounts.begin();
- i != amounts.end();
- i++)
- (*i).second.abs();
- }
-
- void reduce() {
- for (amounts_map::iterator i = amounts.begin();
- i != amounts.end();
- i++)
- (*i).second.reduce();
- }
-
- balance_t reduced() const {
- balance_t temp(*this);
- temp.reduce();
- return temp;
- }
-
- void round() {
- for (amounts_map::iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second.commodity())
- (*i).second = (*i).second.round();
- }
-
- balance_t unround() const {
- balance_t temp;
- for (amounts_map::const_iterator i = amounts.begin();
- i != amounts.end();
- i++)
- if ((*i).second.commodity())
- temp += (*i).second.unround();
- return temp;
- }
-};
-
-inline balance_t abs(const balance_t& bal) {
- balance_t temp = bal;
- temp.abs();
- return temp;
-}
-
-inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) {
- bal.write(out, 12);
- return out;
-}
-
-class balance_pair_t
-{
- public:
- balance_t quantity;
- balance_t * cost;
-
- // constructors
- balance_pair_t() : cost(NULL) {}
- balance_pair_t(const balance_pair_t& bal_pair)
- : quantity(bal_pair.quantity), cost(NULL) {
- if (bal_pair.cost)
- cost = new balance_t(*bal_pair.cost);
- }
- balance_pair_t(const balance_t& _quantity)
- : quantity(_quantity), cost(NULL) {}
- balance_pair_t(const amount_t& _quantity)
- : quantity(_quantity), cost(NULL) {}
- template <typename T>
- balance_pair_t(T value) : quantity(value), cost(NULL) {}
-
- // destructor
- ~balance_pair_t() {
- if (cost) delete cost;
- }
-
- // assignment operator
- balance_pair_t& operator=(const balance_pair_t& bal_pair) {
- if (this != &bal_pair) {
- if (cost) {
- delete cost;
- cost = NULL;
- }
- quantity = bal_pair.quantity;
- if (bal_pair.cost)
- cost = new balance_t(*bal_pair.cost);
- }
- return *this;
- }
- balance_pair_t& operator=(const balance_t& bal) {
- if (cost) {
- delete cost;
- cost = NULL;
- }
- quantity = bal;
- return *this;
- }
- balance_pair_t& operator=(const amount_t& amt) {
- if (cost) {
- delete cost;
- cost = NULL;
- }
- quantity = amt;
- return *this;
- }
- template <typename T>
- balance_pair_t& operator=(T value) {
- if (cost) {
- delete cost;
- cost = NULL;
- }
- quantity = value;
- return *this;
- }
-
- // in-place arithmetic
- balance_pair_t& operator+=(const balance_pair_t& bal_pair) {
- if (bal_pair.cost && ! cost)
- cost = new balance_t(quantity);
- quantity += bal_pair.quantity;
- if (cost)
- *cost += bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
- return *this;
- }
- balance_pair_t& operator+=(const balance_t& bal) {
- quantity += bal;
- if (cost)
- *cost += bal;
- return *this;
- }
- balance_pair_t& operator+=(const amount_t& amt) {
- quantity += amt;
- if (cost)
- *cost += amt;
- return *this;
- }
- template <typename T>
- balance_pair_t& operator+=(T val) {
- return *this += amount_t(val);
- }
-
- balance_pair_t& operator-=(const balance_pair_t& bal_pair) {
- if (bal_pair.cost && ! cost)
- cost = new balance_t(quantity);
- quantity -= bal_pair.quantity;
- if (cost)
- *cost -= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
- return *this;
- }
- balance_pair_t& operator-=(const balance_t& bal) {
- quantity -= bal;
- if (cost)
- *cost -= bal;
- return *this;
- }
- balance_pair_t& operator-=(const amount_t& amt) {
- quantity -= amt;
- if (cost)
- *cost -= amt;
- return *this;
- }
- template <typename T>
- balance_pair_t& operator-=(T val) {
- return *this -= amount_t(val);
- }
-
- // simple arithmetic
- balance_pair_t operator+(const balance_pair_t& bal_pair) const {
- balance_pair_t temp = *this;
- temp += bal_pair;
- return temp;
- }
- balance_pair_t operator+(const balance_t& bal) const {
- balance_pair_t temp = *this;
- temp += bal;
- return temp;
- }
- balance_pair_t operator+(const amount_t& amt) const {
- balance_pair_t temp = *this;
- temp += amt;
- return temp;
- }
- template <typename T>
- balance_pair_t operator+(T val) const {
- balance_pair_t temp = *this;
- temp += val;
- return temp;
- }
-
- balance_pair_t operator-(const balance_pair_t& bal_pair) const {
- balance_pair_t temp = *this;
- temp -= bal_pair;
- return temp;
- }
- balance_pair_t operator-(const balance_t& bal) const {
- balance_pair_t temp = *this;
- temp -= bal;
- return temp;
- }
- balance_pair_t operator-(const amount_t& amt) const {
- balance_pair_t temp = *this;
- temp -= amt;
- return temp;
- }
- template <typename T>
- balance_pair_t operator-(T val) const {
- balance_pair_t temp = *this;
- temp -= val;
- return temp;
- }
-
- // multiplication and division
- balance_pair_t& operator*=(const balance_pair_t& bal_pair) {
- if (bal_pair.cost && ! cost)
- cost = new balance_t(quantity);
- quantity *= bal_pair.quantity;
- if (cost)
- *cost *= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
- return *this;
- }
- balance_pair_t& operator*=(const balance_t& bal) {
- quantity *= bal;
- if (cost)
- *cost *= bal;
- return *this;
- }
- balance_pair_t& operator*=(const amount_t& amt) {
- quantity *= amt;
- if (cost)
- *cost *= amt;
- return *this;
- }
- template <typename T>
- balance_pair_t& operator*=(T val) {
- return *this *= amount_t(val);
- }
-
- balance_pair_t& operator/=(const balance_pair_t& bal_pair) {
- if (bal_pair.cost && ! cost)
- cost = new balance_t(quantity);
- quantity /= bal_pair.quantity;
- if (cost)
- *cost /= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
- return *this;
- }
- balance_pair_t& operator/=(const balance_t& bal) {
- quantity /= bal;
- if (cost)
- *cost /= bal;
- return *this;
- }
- balance_pair_t& operator/=(const amount_t& amt) {
- quantity /= amt;
- if (cost)
- *cost /= amt;
- return *this;
- }
- template <typename T>
- balance_pair_t& operator/=(T val) {
- return *this /= amount_t(val);
- }
-
- balance_pair_t operator*(const balance_pair_t& bal_pair) const {
- balance_pair_t temp = *this;
- temp *= bal_pair;
- return temp;
- }
- balance_pair_t operator*(const balance_t& bal) const {
- balance_pair_t temp = *this;
- temp *= bal;
- return temp;
- }
- balance_pair_t operator*(const amount_t& amt) const {
- balance_pair_t temp = *this;
- temp *= amt;
- return temp;
- }
- template <typename T>
- balance_pair_t operator*(T val) const {
- balance_pair_t temp = *this;
- temp *= val;
- return temp;
- }
-
- balance_pair_t operator/(const balance_pair_t& bal_pair) const {
- balance_pair_t temp = *this;
- temp /= bal_pair;
- return temp;
- }
- balance_pair_t operator/(const balance_t& bal) const {
- balance_pair_t temp = *this;
- temp /= bal;
- return temp;
- }
- balance_pair_t operator/(const amount_t& amt) const {
- balance_pair_t temp = *this;
- temp /= amt;
- return temp;
- }
- template <typename T>
- balance_pair_t operator/(T val) const {
- balance_pair_t temp = *this;
- temp /= val;
- return temp;
- }
-
- // comparison
- bool operator<(const balance_pair_t& bal_pair) const {
- return quantity < bal_pair.quantity;
- }
- bool operator<(const balance_t& bal) const {
- return quantity < bal;
- }
- bool operator<(const amount_t& amt) const {
- return quantity < amt;
- }
- template <typename T>
- bool operator<(T val) const {
- return quantity < val;
- }
-
- bool operator<=(const balance_pair_t& bal_pair) const {
- return quantity <= bal_pair.quantity;
- }
- bool operator<=(const balance_t& bal) const {
- return quantity <= bal;
- }
- bool operator<=(const amount_t& amt) const {
- return quantity <= amt;
- }
- template <typename T>
- bool operator<=(T val) const {
- return quantity <= val;
- }
-
- bool operator>(const balance_pair_t& bal_pair) const {
- return quantity > bal_pair.quantity;
- }
- bool operator>(const balance_t& bal) const {
- return quantity > bal;
- }
- bool operator>(const amount_t& amt) const {
- return quantity > amt;
- }
- template <typename T>
- bool operator>(T val) const {
- return quantity > val;
- }
-
- bool operator>=(const balance_pair_t& bal_pair) const {
- return quantity >= bal_pair.quantity;
- }
- bool operator>=(const balance_t& bal) const {
- return quantity >= bal;
- }
- bool operator>=(const amount_t& amt) const {
- return quantity >= amt;
- }
- template <typename T>
- bool operator>=(T val) const {
- return quantity >= val;
- }
-
- bool operator==(const balance_pair_t& bal_pair) const {
- return quantity == bal_pair.quantity;
- }
- bool operator==(const balance_t& bal) const {
- return quantity == bal;
- }
- bool operator==(const amount_t& amt) const {
- return quantity == amt;
- }
- template <typename T>
- bool operator==(T val) const {
- return quantity == val;
- }
-
- bool operator!=(const balance_pair_t& bal_pair) const {
- return ! (*this == bal_pair);
- }
- bool operator!=(const balance_t& bal) const {
- return ! (*this == bal);
- }
- bool operator!=(const amount_t& amt) const {
- return ! (*this == amt);
- }
- template <typename T>
- bool operator!=(T val) const {
- return ! (*this == val);
- }
-
- // unary negation
- void negate() {
- quantity.negate();
- if (cost) cost->negate();
- }
- balance_pair_t negated() const {
- balance_pair_t temp = *this;
- temp.negate();
- return temp;
- }
- balance_pair_t operator-() const {
- return negated();
- }
-
- // test for non-zero (use ! for zero)
- operator balance_t() const {
- return quantity;
- }
- operator amount_t() const {
- return quantity;
- }
- operator bool() const {
- return quantity;
- }
-
- bool realzero() const {
- return ((! cost || cost->realzero()) && quantity.realzero());
- }
-
- void abs() {
- quantity.abs();
- if (cost) cost->abs();
- }
-
- amount_t amount(const commodity_t& commodity =
- *commodity_t::null_commodity) const {
- return quantity.amount(commodity);
- }
- balance_t value(const datetime_t& moment = datetime_t::now) const {
- return quantity.value(moment);
- }
- balance_t price() const {
- return quantity.price();
- }
- datetime_t date() const {
- return quantity.date();
- }
-
- balance_t
- strip_annotations(const bool keep_price = amount_t::keep_price,
- const bool keep_date = amount_t::keep_date,
- const bool keep_tag = amount_t::keep_tag) const {
- return quantity.strip_annotations(keep_price, keep_date, keep_tag);
- }
-
- void write(std::ostream& out, const int first_width,
- const int latter_width = -1) const {
- quantity.write(out, first_width, latter_width);
- }
-
- balance_pair_t& add(const amount_t& amount,
- const amount_t * a_cost = NULL) {
- if (a_cost && ! cost)
- cost = new balance_t(quantity);
- quantity += amount;
- if (cost)
- *cost += a_cost ? *a_cost : amount;
- return *this;
- }
-
- bool valid() {
- return quantity.valid() && (! cost || cost->valid());
- }
-
- void reduce() {
- quantity.reduce();
- if (cost) cost->reduce();
- }
-
- balance_pair_t reduced() const {
- balance_pair_t temp(*this);
- temp.reduce();
- return temp;
- }
-
- void round() {
- quantity.round();
- if (cost) cost->round();
- }
-
- balance_pair_t unround() {
- balance_pair_t temp(quantity.unround());
- if (cost)
- temp.cost = new balance_t(cost->unround());
- return temp;
- }
-
- friend inline bool operator<(const balance_t& bal, const balance_pair_t& bal_pair) {
- return bal_pair >= bal;
- }
- friend inline bool operator<=(const balance_t& bal, const balance_pair_t& bal_pair) {
- return bal_pair > bal;
- }
- friend inline bool operator>(const balance_t& bal, const balance_pair_t& bal_pair) {
- return bal_pair <= bal;
- }
- friend inline bool operator>=(const balance_t& bal, const balance_pair_t& bal_pair) {
- return bal_pair < bal;
- }
- friend inline bool operator==(const balance_t& bal, const balance_pair_t& bal_pair) {
- return bal_pair == bal;
- }
-};
-
-inline balance_pair_t abs(const balance_pair_t& bal_pair) {
- balance_pair_t temp;
- temp.abs();
- return temp;
-}
-
-inline std::ostream& operator<<(std::ostream& out,
- const balance_pair_t& bal_pair) {
- bal_pair.quantity.write(out, 12);
- return out;
-}
-
-} // namespace ledger
-
-#endif // _BALANCE_H
diff --git a/binary.cc b/binary.cc
deleted file mode 100644
index 295fc1bc..00000000
--- a/binary.cc
+++ /dev/null
@@ -1,1338 +0,0 @@
-#include "journal.h"
-#include "valexpr.h"
-#include "binary.h"
-
-#include <fstream>
-#include <sys/stat.h>
-
-#define TIMELOG_SUPPORT 1
-
-namespace ledger {
-
-static unsigned long binary_magic_number = 0xFFEED765;
-#ifdef DEBUG_ENABLED
-static unsigned long format_version = 0x0002060d;
-#else
-static unsigned long format_version = 0x0002060c;
-#endif
-
-static account_t ** accounts;
-static account_t ** accounts_next;
-static unsigned int account_index;
-
-static commodity_base_t ** base_commodities;
-static commodity_base_t ** base_commodities_next;
-static unsigned int base_commodity_index;
-
-static commodity_t ** commodities;
-static commodity_t ** commodities_next;
-static unsigned int commodity_index;
-
-extern char * bigints;
-extern char * bigints_next;
-extern unsigned int bigints_index;
-extern unsigned int bigints_count;
-
-template <typename T>
-inline void read_binary_number_nocheck(std::istream& in, T& num) {
- in.read((char *)&num, sizeof(num));
-}
-
-template <typename T>
-inline T read_binary_number_nocheck(std::istream& in) {
- T num;
- read_binary_number_nocheck(in, num);
- return num;
-}
-
-template <typename T>
-inline void read_binary_number_nocheck(char *& data, T& num) {
- num = *((T *) data);
- data += sizeof(T);
-}
-
-template <typename T>
-inline T read_binary_number_nocheck(char *& data) {
- T num;
- read_binary_number_nocheck(data, num);
- return num;
-}
-
-#if DEBUG_LEVEL >= ALPHA
-static void assert_failed() {
- assert(0);
-}
-#define read_binary_guard(in, id) \
- if (read_binary_number_nocheck<unsigned short>(in) != id) \
- assert_failed();
-#else
-#define read_binary_guard(in, id)
-#endif
-
-template <typename T>
-inline void read_binary_number(std::istream& in, T& num) {
- read_binary_guard(in, 0x2003);
- in.read((char *)&num, sizeof(num));
- read_binary_guard(in, 0x2004);
-}
-
-inline void read_binary_bool(std::istream& in, bool& num) {
- read_binary_guard(in, 0x2005);
- unsigned char val;
- in.read((char *)&val, sizeof(val));
- num = val == 1;
- read_binary_guard(in, 0x2006);
-}
-
-template <typename T>
-inline void read_binary_long(std::istream& in, T& num) {
- read_binary_guard(in, 0x2001);
-
- unsigned char len;
- read_binary_number_nocheck(in, len);
-
- num = 0;
- unsigned char temp;
- if (len > 3) {
- read_binary_number_nocheck(in, temp);
- num |= ((unsigned long)temp) << 24;
- }
- if (len > 2) {
- read_binary_number_nocheck(in, temp);
- num |= ((unsigned long)temp) << 16;
- }
- if (len > 1) {
- read_binary_number_nocheck(in, temp);
- num |= ((unsigned long)temp) << 8;
- }
-
- read_binary_number_nocheck(in, temp);
- num |= ((unsigned long)temp);
-
- read_binary_guard(in, 0x2002);
-}
-
-template <typename T>
-inline T read_binary_number(std::istream& in) {
- T num;
- read_binary_number(in, num);
- return num;
-}
-
-inline bool read_binary_bool(std::istream& in) {
- bool num;
- read_binary_bool(in, num);
- return num;
-}
-
-template <typename T>
-inline T read_binary_long(std::istream& in) {
- T num;
- read_binary_long(in, num);
- return num;
-}
-
-inline void read_binary_string(std::istream& in, std::string& str)
-{
- read_binary_guard(in, 0x3001);
-
- unsigned char len;
- read_binary_number_nocheck(in, len);
- if (len == 0xff) {
- unsigned short slen;
- read_binary_number_nocheck(in, slen);
- char * buf = new char[slen + 1];
- in.read(buf, slen);
- buf[slen] = '\0';
- str = buf;
- delete[] buf;
- }
- else if (len) {
- char buf[256];
- in.read(buf, len);
- buf[len] = '\0';
- str = buf;
- } else {
- str = "";
- }
-
- read_binary_guard(in, 0x3002);
-}
-
-inline std::string read_binary_string(std::istream& in) {
- std::string temp;
- read_binary_string(in, temp);
- return temp;
-}
-
-template <typename T>
-inline void read_binary_number(char *& data, T& num) {
- read_binary_guard(data, 0x2003);
- num = *((T *) data);
- data += sizeof(T);
- read_binary_guard(data, 0x2004);
-}
-
-inline void read_binary_bool(char *& data, bool& num) {
- read_binary_guard(data, 0x2005);
- unsigned char val = *((unsigned char *) data);
- data += sizeof(unsigned char);
- num = val == 1;
- read_binary_guard(data, 0x2006);
-}
-
-template <typename T>
-inline void read_binary_long(char *& data, T& num) {
- read_binary_guard(data, 0x2001);
-
- unsigned char len;
- read_binary_number_nocheck(data, len);
-
- num = 0;
- unsigned char temp;
- if (len > 3) {
- read_binary_number_nocheck(data, temp);
- num |= ((unsigned long)temp) << 24;
- }
- if (len > 2) {
- read_binary_number_nocheck(data, temp);
- num |= ((unsigned long)temp) << 16;
- }
- if (len > 1) {
- read_binary_number_nocheck(data, temp);
- num |= ((unsigned long)temp) << 8;
- }
-
- read_binary_number_nocheck(data, temp);
- num |= ((unsigned long)temp);
-
- read_binary_guard(data, 0x2002);
-}
-
-template <typename T>
-inline T read_binary_number(char *& data) {
- T num;
- read_binary_number(data, num);
- return num;
-}
-
-inline bool read_binary_bool(char *& data) {
- bool num;
- read_binary_bool(data, num);
- return num;
-}
-
-template <typename T>
-inline T read_binary_long(char *& data) {
- T num;
- read_binary_long(data, num);
- return num;
-}
-
-inline void read_binary_string(char *& data, std::string& str)
-{
- read_binary_guard(data, 0x3001);
-
- unsigned char len;
- read_binary_number_nocheck(data, len);
- if (len == 0xff) {
- unsigned short slen;
- read_binary_number_nocheck(data, slen);
- str = std::string(data, slen);
- data += slen;
- }
- else if (len) {
- str = std::string(data, len);
- data += len;
- }
- else {
- str = "";
- }
-
- read_binary_guard(data, 0x3002);
-}
-
-inline std::string read_binary_string(char *& data)
-{
- std::string temp;
- read_binary_string(data, temp);
- return temp;
-}
-
-inline void read_binary_string(char *& data, std::string * str)
-{
- read_binary_guard(data, 0x3001);
-
- unsigned char len;
- read_binary_number_nocheck(data, len);
- if (len == 0xff) {
- unsigned short slen;
- read_binary_number_nocheck(data, slen);
- new(str) std::string(data, slen);
- data += slen;
- }
- else if (len) {
- new(str) std::string(data, len);
- data += len;
- }
- else {
- new(str) std::string("");
- }
-
- read_binary_guard(data, 0x3002);
-}
-
-inline void read_binary_amount(char *& data, amount_t& amt)
-{
- commodity_t::ident_t ident;
- read_binary_long(data, ident);
- if (ident == 0xffffffff)
- amt.commodity_ = NULL;
- else if (ident == 0)
- amt.commodity_ = commodity_t::null_commodity;
- else
- amt.commodity_ = commodities[ident - 1];
-
- amt.read_quantity(data);
-}
-
-inline void read_binary_value(char *& data, value_t& val)
-{
- val.type = static_cast<value_t::type_t>(read_binary_long<int>(data));
-
- switch (val.type) {
- case value_t::BOOLEAN:
- read_binary_bool(data, *((bool *) val.data));
- break;
- case value_t::INTEGER:
- read_binary_long(data, *((long *) val.data));
- break;
- case value_t::DATETIME:
- read_binary_number(data, *((datetime_t *) val.data));
- break;
- case value_t::AMOUNT:
- read_binary_amount(data, *((amount_t *) val.data));
- break;
-
- case value_t::BALANCE:
- case value_t::BALANCE_PAIR:
- assert(0);
- break;
- }
-}
-
-inline void read_binary_mask(char *& data, mask_t *& mask)
-{
- bool exclude;
- read_binary_number(data, exclude);
- std::string pattern;
- read_binary_string(data, pattern);
-
- mask = new mask_t(pattern);
- mask->exclude = exclude;
-}
-
-inline void read_binary_value_expr(char *& data, value_expr_t *& expr)
-{
- if (! read_binary_bool(data)) {
- expr = NULL;
- return;
- }
-
- value_expr_t::kind_t kind;
- read_binary_number(data, kind);
-
- expr = new value_expr_t(kind);
-
- if (kind > value_expr_t::TERMINALS) {
- read_binary_value_expr(data, expr->left);
- if (expr->left) expr->left->acquire();
- }
-
- switch (expr->kind) {
- case value_expr_t::O_ARG:
- case value_expr_t::INDEX:
- read_binary_long(data, expr->arg_index);
- break;
- case value_expr_t::CONSTANT:
- expr->value = new value_t;
- read_binary_value(data, *expr->value);
- break;
-
- case value_expr_t::F_CODE_MASK:
- case value_expr_t::F_PAYEE_MASK:
- case value_expr_t::F_NOTE_MASK:
- case value_expr_t::F_ACCOUNT_MASK:
- case value_expr_t::F_SHORT_ACCOUNT_MASK:
- case value_expr_t::F_COMMODITY_MASK:
- if (read_binary_bool(data))
- read_binary_mask(data, expr->mask);
- break;
-
- default:
- if (kind > value_expr_t::TERMINALS) {
- read_binary_value_expr(data, expr->right);
- if (expr->right) expr->right->acquire();
- }
- break;
- }
-}
-
-
-inline void read_binary_transaction(char *& data, transaction_t * xact)
-{
- read_binary_number(data, xact->_date);
- read_binary_number(data, xact->_date_eff);
- xact->account = accounts[read_binary_long<account_t::ident_t>(data) - 1];
-
- unsigned char flag = read_binary_number<unsigned char>(data);
- if (flag == 0) {
- read_binary_amount(data, xact->amount);
- }
- else if (flag == 1) {
- read_binary_amount(data, xact->amount);
- read_binary_string(data, xact->amount_expr.expr);
- }
- else {
- value_expr_t * ptr = NULL;
- read_binary_value_expr(data, ptr);
- assert(ptr);
- xact->amount_expr.reset(ptr);
- read_binary_string(data, xact->amount_expr.expr);
- }
-
- if (read_binary_bool(data)) {
- xact->cost = new amount_t;
- read_binary_amount(data, *xact->cost);
- read_binary_string(data, xact->cost_expr);
- } else {
- xact->cost = NULL;
- }
-
- read_binary_number(data, xact->state);
- read_binary_number(data, xact->flags);
- xact->flags |= TRANSACTION_BULK_ALLOC;
- read_binary_string(data, &xact->note);
-
- xact->beg_pos = read_binary_long<unsigned long>(data);
- read_binary_long(data, xact->beg_line);
- xact->end_pos = read_binary_long<unsigned long>(data);
- read_binary_long(data, xact->end_line);
-
- xact->data = NULL;
-
- if (xact->amount_expr)
- compute_amount(xact->amount_expr, xact->amount, xact);
-}
-
-inline void read_binary_entry_base(char *& data, entry_base_t * entry,
- transaction_t *& xact_pool, bool& finalize)
-{
- read_binary_long(data, entry->src_idx);
- entry->beg_pos = read_binary_long<unsigned long>(data);
- read_binary_long(data, entry->beg_line);
- entry->end_pos = read_binary_long<unsigned long>(data);
- read_binary_long(data, entry->end_line);
-
- bool ignore_calculated = read_binary_bool(data);
-
- for (unsigned long i = 0, count = read_binary_long<unsigned long>(data);
- i < count;
- i++) {
- new(xact_pool) transaction_t;
- read_binary_transaction(data, xact_pool);
- if (ignore_calculated && xact_pool->flags & TRANSACTION_CALCULATED)
- finalize = true;
- entry->add_transaction(xact_pool++);
- }
-}
-
-inline void read_binary_entry(char *& data, entry_t * entry,
- transaction_t *& xact_pool, bool& finalize)
-{
- read_binary_entry_base(data, entry, xact_pool, finalize);
- read_binary_number(data, entry->_date);
- read_binary_number(data, entry->_date_eff);
- read_binary_string(data, &entry->code);
- read_binary_string(data, &entry->payee);
-}
-
-inline void read_binary_auto_entry(char *& data, auto_entry_t * entry,
- transaction_t *& xact_pool)
-{
- bool ignore;
- read_binary_entry_base(data, entry, xact_pool, ignore);
- value_expr_t * expr;
- read_binary_value_expr(data, expr);
- // the item_predicate constructor will acquire the reference
- entry->predicate = new item_predicate<transaction_t>(expr);
-}
-
-inline void read_binary_period_entry(char *& data, period_entry_t * entry,
- transaction_t *& xact_pool, bool& finalize)
-{
- read_binary_entry_base(data, entry, xact_pool, finalize);
- read_binary_string(data, &entry->period_string);
- std::istringstream stream(entry->period_string);
- entry->period.parse(stream);
-}
-
-inline commodity_base_t * read_binary_commodity_base(char *& data)
-{
- commodity_base_t * commodity = new commodity_base_t;
- *base_commodities_next++ = commodity;
-
- read_binary_string(data, commodity->symbol);
- read_binary_string(data, commodity->name);
- read_binary_string(data, commodity->note);
- read_binary_number(data, commodity->precision);
- read_binary_number(data, commodity->flags);
-
- return commodity;
-}
-
-inline void read_binary_commodity_base_extra(char *& data,
- commodity_t::ident_t ident)
-{
- commodity_base_t * commodity = base_commodities[ident];
-
- bool read_history = false;
- for (unsigned long i = 0, count = read_binary_long<unsigned long>(data);
- i < count;
- i++) {
- datetime_t when;
- read_binary_number(data, when);
- amount_t amt;
- read_binary_amount(data, amt);
-
- // Upon insertion, amt will be copied, which will cause the amount
- // to be duplicated (and thus not lost when the journal's
- // item_pool is deleted).
- if (! commodity->history)
- commodity->history = new commodity_base_t::history_t;
- commodity->history->prices.insert(history_pair(when, amt));
-
- read_history = true;
- }
- if (read_history)
- read_binary_number(data, commodity->history->last_lookup);
-
- if (read_binary_bool(data)) {
- amount_t amt;
- read_binary_amount(data, amt);
- commodity->smaller = new amount_t(amt);
- }
-
- if (read_binary_bool(data)) {
- amount_t amt;
- read_binary_amount(data, amt);
- commodity->larger = new amount_t(amt);
- }
-}
-
-inline commodity_t * read_binary_commodity(char *& data)
-{
- commodity_t * commodity = new commodity_t;
- *commodities_next++ = commodity;
-
- commodity->base =
- base_commodities[read_binary_long<commodity_base_t::ident_t>(data) - 1];
-
- read_binary_string(data, commodity->qualified_symbol);
- commodity->annotated = false;
-
- return commodity;
-}
-
-inline commodity_t * read_binary_commodity_annotated(char *& data)
-{
- annotated_commodity_t * commodity = new annotated_commodity_t;
- *commodities_next++ = commodity;
-
- commodity->base =
- base_commodities[read_binary_long<commodity_base_t::ident_t>(data) - 1];
-
- read_binary_string(data, commodity->qualified_symbol);
- commodity->annotated = true;
-
- commodity->ptr =
- commodities[read_binary_long<commodity_t::ident_t>(data) - 1];
-
- // This read-and-then-assign causes a new amount to be allocated
- // which does not live within the bulk allocation pool, since that
- // pool will be deleted *before* the commodities are destroyed.
- amount_t amt;
- read_binary_amount(data, amt);
- commodity->price = amt;
-
- read_binary_number(data, commodity->date);
- read_binary_string(data, commodity->tag);
-
- return commodity;
-}
-
-inline
-account_t * read_binary_account(char *& data, journal_t * journal,
- account_t * master = NULL)
-{
- account_t * acct = new account_t(NULL);
- *accounts_next++ = acct;
-
- acct->journal = journal;
-
- account_t::ident_t id;
- read_binary_long(data, id); // parent id
- if (id == 0xffffffff)
- acct->parent = NULL;
- else
- acct->parent = accounts[id - 1];
-
- read_binary_string(data, acct->name);
- read_binary_string(data, acct->note);
- read_binary_number(data, acct->depth);
-
- // If all of the subaccounts will be added to a different master
- // account, throw away what we've learned about the recorded
- // journal's own master account.
-
- if (master && acct != master) {
- delete acct;
- acct = master;
- }
-
- for (account_t::ident_t i = 0,
- count = read_binary_long<account_t::ident_t>(data);
- i < count;
- i++) {
- account_t * child = read_binary_account(data, journal);
- child->parent = acct;
- assert(acct != child);
- acct->add_account(child);
- }
-
- return acct;
-}
-
-unsigned int read_binary_journal(std::istream& in,
- const std::string& file,
- journal_t * journal,
- account_t * master)
-{
- account_index =
- base_commodity_index =
- commodity_index = 0;
-
- // Read in the files that participated in this journal, so that they
- // can be checked for changes on reading.
-
- if (! file.empty()) {
- for (unsigned short i = 0,
- count = read_binary_number<unsigned short>(in);
- i < count;
- i++) {
- std::string path = read_binary_string(in);
- std::time_t old_mtime;
- read_binary_number(in, old_mtime);
- struct stat info;
- stat(path.c_str(), &info);
- if (std::difftime(info.st_mtime, old_mtime) > 0)
- return 0;
-
- journal->sources.push_back(path);
- }
-
- // Make sure that the cache uses the same price database,
- // otherwise it means that LEDGER_PRICE_DB has been changed, and
- // we should ignore this cache file.
- if (read_binary_string(in) != journal->price_db)
- return 0;
- }
-
- // Read all of the data in at once, so that we're just dealing with
- // a big data buffer.
-
- unsigned long data_size = read_binary_number<unsigned long>(in);
-
- char * data_pool = new char[data_size];
- char * data = data_pool;
- in.read(data, data_size);
-
- // Read in the accounts
-
- account_t::ident_t a_count = read_binary_long<account_t::ident_t>(data);
- accounts = accounts_next = new account_t *[a_count];
-
- assert(journal->master);
- delete journal->master;
- journal->master = read_binary_account(data, journal, master);
-
- if (read_binary_bool(data))
- journal->basket = accounts[read_binary_long<account_t::ident_t>(data) - 1];
-
- // Allocate the memory needed for the entries and transactions in
- // one large block, which is then chopped up and custom constructed
- // as necessary.
-
- unsigned long count = read_binary_long<unsigned long>(data);
- unsigned long auto_count = read_binary_long<unsigned long>(data);
- unsigned long period_count = read_binary_long<unsigned long>(data);
- unsigned long xact_count = read_binary_number<unsigned long>(data);
- unsigned long bigint_count = read_binary_number<unsigned long>(data);
-
- std::size_t pool_size = (sizeof(entry_t) * count +
- sizeof(transaction_t) * xact_count +
- sizeof_bigint_t() * bigint_count);
-
- char * item_pool = new char[pool_size];
-
- journal->item_pool = item_pool;
- journal->item_pool_end = item_pool + pool_size;
-
- entry_t * entry_pool = (entry_t *) item_pool;
- transaction_t * xact_pool = (transaction_t *) (item_pool +
- sizeof(entry_t) * count);
- bigints_index = 0;
- bigints = bigints_next = (item_pool + sizeof(entry_t) * count +
- sizeof(transaction_t) * xact_count);
-
- // Read in the base commodities and then derived commodities
-
- commodity_base_t::ident_t bc_count =
- read_binary_long<commodity_base_t::ident_t>(data);
- base_commodities = base_commodities_next = new commodity_base_t *[bc_count];
-
- for (commodity_base_t::ident_t i = 0; i < bc_count; i++) {
- commodity_base_t * commodity = read_binary_commodity_base(data);
-
- std::pair<base_commodities_map::iterator, bool> result =
- commodity_base_t::commodities.insert
- (base_commodities_pair(commodity->symbol, commodity));
- if (! result.second) {
- base_commodities_map::iterator c =
- commodity_base_t::commodities.find(commodity->symbol);
-
- // It's possible the user might have used a commodity in a value
- // expression passed to an option, we'll just override the
- // flags, but keep the commodity pointer intact.
- if (c == commodity_base_t::commodities.end())
- throw new error(std::string("Failed to read base commodity from cache: ") +
- commodity->symbol);
-
- (*c).second->name = commodity->name;
- (*c).second->note = commodity->note;
- (*c).second->precision = commodity->precision;
- (*c).second->flags = commodity->flags;
- if ((*c).second->smaller)
- delete (*c).second->smaller;
- (*c).second->smaller = commodity->smaller;
- if ((*c).second->larger)
- delete (*c).second->larger;
- (*c).second->larger = commodity->larger;
-
- *(base_commodities_next - 1) = (*c).second;
- delete commodity;
- }
- }
-
- commodity_t::ident_t c_count = read_binary_long<commodity_t::ident_t>(data);
- commodities = commodities_next = new commodity_t *[c_count];
-
- for (commodity_t::ident_t i = 0; i < c_count; i++) {
- commodity_t * commodity;
- std::string mapping_key;
-
- if (! read_binary_bool(data)) {
- commodity = read_binary_commodity(data);
- mapping_key = commodity->base->symbol;
- } else {
- read_binary_string(data, mapping_key);
- commodity = read_binary_commodity_annotated(data);
- }
-
- std::pair<commodities_map::iterator, bool> result =
- commodity_t::commodities.insert(commodities_pair
- (mapping_key, commodity));
- if (! result.second) {
- commodities_map::iterator c =
- commodity_t::commodities.find(mapping_key);
- if (c == commodity_t::commodities.end())
- throw new error(std::string("Failed to read commodity from cache: ") +
- commodity->symbol());
-
- *(commodities_next - 1) = (*c).second;
- delete commodity;
- }
- }
-
- for (commodity_base_t::ident_t i = 0; i < bc_count; i++)
- read_binary_commodity_base_extra(data, i);
-
- commodity_t::ident_t ident;
- read_binary_long(data, ident);
- if (ident == 0xffffffff || ident == 0)
- commodity_t::default_commodity = NULL;
- else
- commodity_t::default_commodity = commodities[ident - 1];
-
- // Read in the entries and transactions
-
- for (unsigned long i = 0; i < count; i++) {
- new(entry_pool) entry_t;
- bool finalize = false;
- read_binary_entry(data, entry_pool, xact_pool, finalize);
- entry_pool->journal = journal;
- if (finalize && ! entry_pool->finalize())
- continue;
- journal->entries.push_back(entry_pool++);
- }
-
- for (unsigned long i = 0; i < auto_count; i++) {
- auto_entry_t * auto_entry = new auto_entry_t;
- read_binary_auto_entry(data, auto_entry, xact_pool);
- auto_entry->journal = journal;
- journal->auto_entries.push_back(auto_entry);
- }
-
- for (unsigned long i = 0; i < period_count; i++) {
- period_entry_t * period_entry = new period_entry_t;
- bool finalize = false;
- read_binary_period_entry(data, period_entry, xact_pool, finalize);
- period_entry->journal = journal;
- if (finalize && ! period_entry->finalize())
- continue;
- journal->period_entries.push_back(period_entry);
- }
-
- // Clean up and return the number of entries read
-
- delete[] accounts;
- delete[] commodities;
- delete[] data_pool;
-
- VALIDATE(journal->valid());
-
- return count;
-}
-
-bool binary_parser_t::test(std::istream& in) const
-{
- if (read_binary_number_nocheck<unsigned long>(in) == binary_magic_number &&
- read_binary_number_nocheck<unsigned long>(in) == format_version)
- return true;
-
- in.clear();
- in.seekg(0, std::ios::beg);
- return false;
-}
-
-unsigned int binary_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
-{
- return read_binary_journal(in, original_file ? *original_file : "",
- journal, master);
-}
-
-template <typename T>
-inline void write_binary_number_nocheck(std::ostream& out, T num) {
- out.write((char *)&num, sizeof(num));
-}
-
-#if DEBUG_LEVEL >= ALPHA
-#define write_binary_guard(out, id) \
- write_binary_number_nocheck<unsigned short>(out, id)
-#else
-#define write_binary_guard(in, id)
-#endif
-
-template <typename T>
-inline void write_binary_number(std::ostream& out, T num) {
- write_binary_guard(out, 0x2003);
- out.write((char *)&num, sizeof(num));
- write_binary_guard(out, 0x2004);
-}
-
-inline void write_binary_bool(std::ostream& out, bool num) {
- write_binary_guard(out, 0x2005);
- unsigned char val = num ? 1 : 0;
- out.write((char *)&val, sizeof(val));
- write_binary_guard(out, 0x2006);
-}
-
-template <typename T>
-inline void write_binary_long(std::ostream& out, T num) {
- write_binary_guard(out, 0x2001);
-
- unsigned char len = 4;
- if (((unsigned long)num) < 0x00000100UL)
- len = 1;
- else if (((unsigned long)num) < 0x00010000UL)
- len = 2;
- else if (((unsigned long)num) < 0x01000000UL)
- len = 3;
- write_binary_number_nocheck<unsigned char>(out, len);
-
- unsigned char temp;
- if (len > 3) {
- temp = (((unsigned long)num) & 0xFF000000UL) >> 24;
- write_binary_number_nocheck(out, temp);
- }
- if (len > 2) {
- temp = (((unsigned long)num) & 0x00FF0000UL) >> 16;
- write_binary_number_nocheck(out, temp);
- }
- if (len > 1) {
- temp = (((unsigned long)num) & 0x0000FF00UL) >> 8;
- write_binary_number_nocheck(out, temp);
- }
-
- temp = (((unsigned long)num) & 0x000000FFUL);
- write_binary_number_nocheck(out, temp);
-
- write_binary_guard(out, 0x2002);
-}
-
-inline void write_binary_string(std::ostream& out, const std::string& str)
-{
- write_binary_guard(out, 0x3001);
-
- unsigned long len = str.length();
- if (len > 255) {
- assert(len < 65536);
- write_binary_number_nocheck<unsigned char>(out, 0xff);
- write_binary_number_nocheck<unsigned short>(out, len);
- } else {
- write_binary_number_nocheck<unsigned char>(out, len);
- }
-
- if (len)
- out.write(str.c_str(), len);
-
- write_binary_guard(out, 0x3002);
-}
-
-void write_binary_amount(std::ostream& out, const amount_t& amt)
-{
- if (amt.commodity_)
- write_binary_long(out, amt.commodity_->ident);
- else
- write_binary_long<commodity_t::ident_t>(out, 0xffffffff);
-
- amt.write_quantity(out);
-}
-
-void write_binary_value(std::ostream& out, const value_t& val)
-{
- write_binary_long(out, (int)val.type);
-
- switch (val.type) {
- case value_t::BOOLEAN:
- write_binary_bool(out, *((bool *) val.data));
- break;
- case value_t::INTEGER:
- write_binary_long(out, *((long *) val.data));
- break;
- case value_t::DATETIME:
- write_binary_number(out, *((datetime_t *) val.data));
- break;
- case value_t::AMOUNT:
- write_binary_amount(out, *((amount_t *) val.data));
- break;
-
- case value_t::BALANCE:
- case value_t::BALANCE_PAIR:
- throw new error("Cannot write a balance to the binary cache");
- }
-}
-
-void write_binary_mask(std::ostream& out, mask_t * mask)
-{
- write_binary_number(out, mask->exclude);
- write_binary_string(out, mask->pattern);
-}
-
-void write_binary_value_expr(std::ostream& out, const value_expr_t * expr)
-{
- if (! expr) {
- write_binary_bool(out, false);
- return;
- }
- write_binary_bool(out, true);
- write_binary_number(out, expr->kind);
-
- if (expr->kind > value_expr_t::TERMINALS)
- write_binary_value_expr(out, expr->left);
-
- switch (expr->kind) {
- case value_expr_t::O_ARG:
- case value_expr_t::INDEX:
- write_binary_long(out, expr->arg_index);
- break;
- case value_expr_t::CONSTANT:
- write_binary_value(out, *expr->value);
- break;
-
- case value_expr_t::F_CODE_MASK:
- case value_expr_t::F_PAYEE_MASK:
- case value_expr_t::F_NOTE_MASK:
- case value_expr_t::F_ACCOUNT_MASK:
- case value_expr_t::F_SHORT_ACCOUNT_MASK:
- case value_expr_t::F_COMMODITY_MASK:
- if (expr->mask) {
- write_binary_bool(out, true);
- write_binary_mask(out, expr->mask);
- } else {
- write_binary_bool(out, false);
- }
- break;
-
- default:
- if (expr->kind > value_expr_t::TERMINALS)
- write_binary_value_expr(out, expr->right);
- break;
- }
-
-}
-
-void write_binary_transaction(std::ostream& out, transaction_t * xact,
- bool ignore_calculated)
-{
- write_binary_number(out, xact->_date);
- write_binary_number(out, xact->_date_eff);
- write_binary_long(out, xact->account->ident);
-
- if (ignore_calculated && xact->flags & TRANSACTION_CALCULATED) {
- write_binary_number<unsigned char>(out, 0);
- write_binary_amount(out, amount_t());
- }
- else if (xact->amount_expr) {
- write_binary_number<unsigned char>(out, 2);
- write_binary_value_expr(out, xact->amount_expr.get());
- write_binary_string(out, xact->amount_expr.expr);
- }
- else if (! xact->amount_expr.expr.empty()) {
- write_binary_number<unsigned char>(out, 1);
- write_binary_amount(out, xact->amount);
- write_binary_string(out, xact->amount_expr.expr);
- }
- else {
- write_binary_number<unsigned char>(out, 0);
- write_binary_amount(out, xact->amount);
- }
-
- if (xact->cost &&
- (! (ignore_calculated && xact->flags & TRANSACTION_CALCULATED))) {
- write_binary_bool(out, true);
- write_binary_amount(out, *xact->cost);
- write_binary_string(out, xact->cost_expr);
- } else {
- write_binary_bool(out, false);
- }
-
- write_binary_number(out, xact->state);
- write_binary_number(out, xact->flags);
- write_binary_string(out, xact->note);
-
- write_binary_long(out, xact->beg_pos);
- write_binary_long(out, xact->beg_line);
- write_binary_long(out, xact->end_pos);
- write_binary_long(out, xact->end_line);
-}
-
-void write_binary_entry_base(std::ostream& out, entry_base_t * entry)
-{
- write_binary_long(out, entry->src_idx);
- write_binary_long(out, entry->beg_pos);
- write_binary_long(out, entry->beg_line);
- write_binary_long(out, entry->end_pos);
- write_binary_long(out, entry->end_line);
-
- bool ignore_calculated = false;
- for (transactions_list::const_iterator i = entry->transactions.begin();
- i != entry->transactions.end();
- i++)
- if ((*i)->amount_expr) {
- ignore_calculated = true;
- break;
- }
-
- write_binary_bool(out, ignore_calculated);
-
- write_binary_long(out, entry->transactions.size());
- for (transactions_list::const_iterator i = entry->transactions.begin();
- i != entry->transactions.end();
- i++)
- write_binary_transaction(out, *i, ignore_calculated);
-}
-
-void write_binary_entry(std::ostream& out, entry_t * entry)
-{
- write_binary_entry_base(out, entry);
- write_binary_number(out, entry->_date);
- write_binary_number(out, entry->_date_eff);
- write_binary_string(out, entry->code);
- write_binary_string(out, entry->payee);
-}
-
-void write_binary_auto_entry(std::ostream& out, auto_entry_t * entry)
-{
- write_binary_entry_base(out, entry);
- write_binary_value_expr(out, entry->predicate->predicate);
-}
-
-void write_binary_period_entry(std::ostream& out, period_entry_t * entry)
-{
- write_binary_entry_base(out, entry);
- write_binary_string(out, entry->period_string);
-}
-
-void write_binary_commodity_base(std::ostream& out, commodity_base_t * commodity)
-{
- commodity->ident = ++base_commodity_index;
-
- write_binary_string(out, commodity->symbol);
- write_binary_string(out, commodity->name);
- write_binary_string(out, commodity->note);
- write_binary_number(out, commodity->precision);
- write_binary_number(out, commodity->flags);
-}
-
-void write_binary_commodity_base_extra(std::ostream& out,
- commodity_base_t * commodity)
-{
- if (commodity->history && commodity->history->bogus_time)
- commodity->remove_price(commodity->history->bogus_time);
-
- if (! commodity->history) {
- write_binary_long<unsigned long>(out, 0);
- } else {
- write_binary_long<unsigned long>(out, commodity->history->prices.size());
- for (history_map::const_iterator i = commodity->history->prices.begin();
- i != commodity->history->prices.end();
- i++) {
- write_binary_number(out, (*i).first);
- write_binary_amount(out, (*i).second);
- }
- write_binary_number(out, commodity->history->last_lookup);
- }
-
- if (commodity->smaller) {
- write_binary_bool(out, true);
- write_binary_amount(out, *commodity->smaller);
- } else {
- write_binary_bool(out, false);
- }
-
- if (commodity->larger) {
- write_binary_bool(out, true);
- write_binary_amount(out, *commodity->larger);
- } else {
- write_binary_bool(out, false);
- }
-}
-
-void write_binary_commodity(std::ostream& out, commodity_t * commodity)
-{
- commodity->ident = ++commodity_index;
-
- write_binary_long(out, commodity->base->ident);
- write_binary_string(out, commodity->qualified_symbol);
-}
-
-void write_binary_commodity_annotated(std::ostream& out,
- commodity_t * commodity)
-{
- commodity->ident = ++commodity_index;
-
- write_binary_long(out, commodity->base->ident);
- write_binary_string(out, commodity->qualified_symbol);
-
- annotated_commodity_t * ann_comm =
- static_cast<annotated_commodity_t *>(commodity);
-
- write_binary_long(out, ann_comm->base->ident);
- write_binary_amount(out, ann_comm->price);
- write_binary_number(out, ann_comm->date);
- write_binary_string(out, ann_comm->tag);
-}
-
-static inline account_t::ident_t count_accounts(account_t * account)
-{
- account_t::ident_t count = 1;
-
- for (accounts_map::iterator i = account->accounts.begin();
- i != account->accounts.end();
- i++)
- count += count_accounts((*i).second);
-
- return count;
-}
-
-void write_binary_account(std::ostream& out, account_t * account)
-{
- account->ident = ++account_index;
-
- if (account->parent)
- write_binary_long(out, account->parent->ident);
- else
- write_binary_long<account_t::ident_t>(out, 0xffffffff);
-
- write_binary_string(out, account->name);
- write_binary_string(out, account->note);
- write_binary_number(out, account->depth);
-
- write_binary_long<account_t::ident_t>(out, account->accounts.size());
- for (accounts_map::iterator i = account->accounts.begin();
- i != account->accounts.end();
- i++)
- write_binary_account(out, (*i).second);
-}
-
-void write_binary_journal(std::ostream& out, journal_t * journal)
-{
- account_index =
- base_commodity_index =
- commodity_index = 0;
-
- write_binary_number_nocheck(out, binary_magic_number);
- write_binary_number_nocheck(out, format_version);
-
- // Write out the files that participated in this journal, so that
- // they can be checked for changes on reading.
-
- if (journal->sources.empty()) {
- write_binary_number<unsigned short>(out, 0);
- } else {
- write_binary_number<unsigned short>(out, journal->sources.size());
- for (strings_list::const_iterator i = journal->sources.begin();
- i != journal->sources.end();
- i++) {
- write_binary_string(out, *i);
- struct stat info;
- stat((*i).c_str(), &info);
- write_binary_number(out, std::time_t(info.st_mtime));
- }
-
- // Write out the price database that relates to this data file, so
- // that if it ever changes the cache can be invalidated.
- write_binary_string(out, journal->price_db);
- }
-
- ostream_pos_type data_val = out.tellp();
- write_binary_number<unsigned long>(out, 0);
-
- // Write out the accounts
-
- write_binary_long<account_t::ident_t>(out, count_accounts(journal->master));
- write_binary_account(out, journal->master);
-
- if (journal->basket) {
- write_binary_bool(out, true);
- write_binary_long(out, journal->basket->ident);
- } else {
- write_binary_bool(out, false);
- }
-
- // Write out the number of entries, transactions, and amounts
-
- write_binary_long<unsigned long>(out, journal->entries.size());
- write_binary_long<unsigned long>(out, journal->auto_entries.size());
- write_binary_long<unsigned long>(out, journal->period_entries.size());
-
- ostream_pos_type xacts_val = out.tellp();
- write_binary_number<unsigned long>(out, 0);
-
- ostream_pos_type bigints_val = out.tellp();
- write_binary_number<unsigned long>(out, 0);
-
- bigints_count = 0;
-
- // Write out the commodities
-
- write_binary_long<commodity_t::ident_t>
- (out, commodity_base_t::commodities.size());
-
- for (base_commodities_map::const_iterator i =
- commodity_base_t::commodities.begin();
- i != commodity_base_t::commodities.end();
- i++)
- write_binary_commodity_base(out, (*i).second);
-
- write_binary_long<commodity_t::ident_t>
- (out, commodity_t::commodities.size());
-
- for (commodities_map::const_iterator i = commodity_t::commodities.begin();
- i != commodity_t::commodities.end();
- i++) {
- if (! (*i).second->annotated) {
- write_binary_bool(out, false);
- write_binary_commodity(out, (*i).second);
- }
- }
-
- for (commodities_map::const_iterator i = commodity_t::commodities.begin();
- i != commodity_t::commodities.end();
- i++) {
- if ((*i).second->annotated) {
- write_binary_bool(out, true);
- write_binary_string(out, (*i).first); // the mapping key
- write_binary_commodity_annotated(out, (*i).second);
- }
- }
-
- // Write out the history and smaller/larger convertible links after
- // both the base and the main commodities have been written, since
- // the amounts in both will refer to the mains.
-
- for (base_commodities_map::const_iterator i =
- commodity_base_t::commodities.begin();
- i != commodity_base_t::commodities.end();
- i++)
- write_binary_commodity_base_extra(out, (*i).second);
-
- if (commodity_t::default_commodity)
- write_binary_long(out, commodity_t::default_commodity->ident);
- else
- write_binary_long<commodity_t::ident_t>(out, 0xffffffff);
-
- // Write out the entries and transactions
-
- unsigned long xact_count = 0;
-
- for (entries_list::const_iterator i = journal->entries.begin();
- i != journal->entries.end();
- i++) {
- write_binary_entry(out, *i);
- xact_count += (*i)->transactions.size();
- }
-
- for (auto_entries_list::const_iterator i = journal->auto_entries.begin();
- i != journal->auto_entries.end();
- i++) {
- write_binary_auto_entry(out, *i);
- xact_count += (*i)->transactions.size();
- }
-
- for (period_entries_list::const_iterator i = journal->period_entries.begin();
- i != journal->period_entries.end();
- i++) {
- write_binary_period_entry(out, *i);
- xact_count += (*i)->transactions.size();
- }
-
- // Back-patch the count for amounts
-
- unsigned long data_size = (((unsigned long) out.tellp()) -
- ((unsigned long) data_val) -
- sizeof(unsigned long));
- out.seekp(data_val);
- write_binary_number<unsigned long>(out, data_size);
- out.seekp(xacts_val);
- write_binary_number<unsigned long>(out, xact_count);
- out.seekp(bigints_val);
- write_binary_number<unsigned long>(out, bigints_count);
-}
-
-} // namespace ledger
diff --git a/binary.h b/binary.h
deleted file mode 100644
index ca3254c9..00000000
--- a/binary.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef _BINARY_H
-#define _BINARY_H
-
-#include "journal.h"
-#include "parser.h"
-
-namespace ledger {
-
-class binary_parser_t : public parser_t
-{
- public:
- virtual bool test(std::istream& in) const;
-
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
-};
-
-void write_binary_journal(std::ostream& out,
- journal_t * journal);
-
-} // namespace ledger
-
-#endif // _BINARY_H
diff --git a/config.cc b/config.cc
deleted file mode 100644
index 847feff7..00000000
--- a/config.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-#include "config.h"
-#include "acconf.h"
-#include "option.h"
-#include "datetime.h"
-#include "quotes.h"
-#include "valexpr.h"
-#include "walk.h"
-
-#include <fstream>
-#include <cstdlib>
-#ifdef WIN32
-#include <io.h>
-#else
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_REALPATH
-extern "C" char *realpath(const char *, char resolved_path[]);
-#endif
-
-#if defined(HAVE_GETPWUID) || defined(HAVE_GETPWNAM)
-#include <pwd.h>
-#endif
-
-namespace ledger {
-
-std::string expand_path(const std::string& path)
-{
- if (path.length() == 0 || path[0] != '~')
- return path;
-
- const char * pfx = NULL;
- std::string::size_type pos = path.find_first_of('/');
-
- if (path.length() == 1 || pos == 1) {
- pfx = std::getenv("HOME");
-#ifdef HAVE_GETPWUID
- if (! pfx) {
- // Punt. We're trying to expand ~/, but HOME isn't set
- struct passwd * pw = getpwuid(getuid());
- if (pw)
- pfx = pw->pw_dir;
- }
-#endif
- }
-#ifdef HAVE_GETPWNAM
- else {
- std::string user(path, 1, pos == std::string::npos ?
- std::string::npos : pos - 1);
- struct passwd * pw = getpwnam(user.c_str());
- if (pw)
- pfx = pw->pw_dir;
- }
-#endif
-
- // if we failed to find an expansion, return the path unchanged.
-
- if (! pfx)
- return path;
-
- std::string result(pfx);
-
- if (pos == std::string::npos)
- return result;
-
- if (result.length() == 0 || result[result.length() - 1] != '/')
- result += '/';
-
- result += path.substr(pos + 1);
-
- return result;
-}
-
-std::string resolve_path(const std::string& path)
-{
- if (path[0] == '~')
- return expand_path(path);
- return path;
-}
-
-config_t::config_t()
-{
- balance_format = "%20T %2_%-a\n";
- register_format = ("%D %-.20P %-.22A %12.67t %!12.80T\n%/"
- "%32|%-.22A %12.67t %!12.80T\n");
- wide_register_format = ("%D %-.35P %-.38A %22.108t %!22.132T\n%/"
- "%48|%-.38A %22.108t %!22.132T\n");
- plot_amount_format = "%D %(@S(@t))\n";
- plot_total_format = "%D %(@S(@T))\n";
- print_format = "\n%d %Y%C%P\n %-34W %12o%n\n%/ %-34W %12o%n\n";
- write_hdr_format = "%d %Y%C%P\n";
- write_xact_format = " %-34W %12o%n\n";
- equity_format = "\n%D %Y%C%P\n%/ %-34W %12t\n";
- prices_format = "%[%Y/%m/%d %H:%M:%S %Z] %-10A %12t %12T\n";
- pricesdb_format = "P %[%Y/%m/%d %H:%M:%S] %A %t\n";
-
- pricing_leeway = 24 * 3600;
-
- download_quotes = false;
- use_cache = false;
- cache_dirty = false;
- debug_mode = false;
- verbose_mode = false;
- trace_mode = false;
-}
-
-//////////////////////////////////////////////////////////////////////
-
-void trace(const std::string& cat, const std::string& str)
-{
- char buf[32];
- std::strftime(buf, 31, "%H:%M:%S", datetime_t::now.localtime());
- std::cerr << buf << " " << cat << ": " << str << std::endl;
-}
-
-void trace_push(const std::string& cat, const std::string& str,
- timing_t& timer)
-{
- timer.start();
- trace(cat, str);
-}
-
-void trace_pop(const std::string& cat, const std::string& str,
- timing_t& timer)
-{
- timer.stop();
- std::ostringstream out;
- out << str << ": " << (double(timer.cumulative) / double(CLOCKS_PER_SEC)) << "s";
- trace(cat, out.str());
-}
-
-} // namespace ledger
diff --git a/config.h b/config.h
deleted file mode 100644
index 3bb8ed0d..00000000
--- a/config.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef _CONFIG_H
-#define _CONFIG_H
-
-#include "ledger.h"
-#include "timing.h"
-
-#include <iostream>
-#include <memory>
-#include <list>
-
-namespace ledger {
-
-class config_t
-{
- public:
- std::string init_file;
- std::string data_file;
- std::string cache_file;
- std::string price_db;
-
- std::string balance_format;
- std::string register_format;
- std::string wide_register_format;
- std::string plot_amount_format;
- std::string plot_total_format;
- std::string print_format;
- std::string write_hdr_format;
- std::string write_xact_format;
- std::string equity_format;
- std::string prices_format;
- std::string pricesdb_format;
-
- std::string date_input_format;
-
- std::string account;
- std::string pager;
-
- unsigned long pricing_leeway;
-
- bool download_quotes;
- bool use_cache;
- bool cache_dirty;
- bool debug_mode;
- bool verbose_mode;
- bool trace_mode;
-
- config_t();
-};
-
-//////////////////////////////////////////////////////////////////////
-
-std::string resolve_path(const std::string& path);
-
-//////////////////////////////////////////////////////////////////////
-
-void trace(const std::string& cat, const std::string& str);
-void trace_push(const std::string& cat, const std::string& str,
- timing_t& timer);
-void trace_pop(const std::string& cat, const std::string& str,
- timing_t& timer);
-
-#define TRACE(cat, msg) if (config.trace_mode) trace(#cat, msg)
-#define TRACE_(cat, msg) if (trace_mode) trace(#cat, msg)
-
-#define TRACE_PUSH(cat, msg) \
- timing_t timer_ ## cat(#cat); \
- if (config.trace_mode) trace_push(#cat, msg, timer_ ## cat)
-#define TRACE_PUSH_(cat, msg) \
- timing_t timer_ ## cat(#cat); \
- if (trace_mode) trace_push(#cat, msg, timer_ ## cat)
-
-#define TRACE_POP(cat, msg) \
- if (config.trace_mode) trace_pop(#cat, msg, timer_ ## cat)
-#define TRACE_POP_(cat, msg) \
- if (trace_mode) trace_pop(#cat, msg, timer_ ## cat)
-
-} // namespace ledger
-
-#endif // _CONFIG_H
diff --git a/configure.in b/configure.in
deleted file mode 100644
index 59a006b9..00000000
--- a/configure.in
+++ /dev/null
@@ -1,280 +0,0 @@
-# -*- Autoconf -*-
-# Process this file with autoconf to produce a configure script.
-
-AC_PREREQ(2.59)
-AC_INIT([ledger],[2.6.1],[johnw@newartisans.com])
-AC_CONFIG_SRCDIR([main.cc])
-AC_CONFIG_HEADER([acconf.h])
-AM_INIT_AUTOMAKE([foreign])
-
-# Checks for programs.
-AC_PROG_CXX
-AC_PROG_MAKE_SET
-AC_PROG_LIBTOOL
-AM_PROG_LIBTOOL
-
-# Checks for emacs lisp path
-AM_PATH_LISPDIR
-
-# check if UNIX pipes are available
-AC_CACHE_CHECK(
- [if pipes can be used],
- [pipes_avail_cv_],
- [AC_LANG_PUSH(C++)
- AC_TRY_LINK(
- [#include <sys/types.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>],
- [int status, pfd[2];
- status = pipe(pfd);
- status = fork();
- if (status < 0) {
- ;
- } else if (status == 0) {
- char *arg0;
-
- status = dup2(pfd[0], STDIN_FILENO);
-
- close(pfd[1]);
- close(pfd[0]);
-
- execlp("", arg0, (char *)0);
- perror("execl");
- exit(1);
- } else {
- close(pfd[0]);
- }],
- [pipes_avail_cv_=true],
- [pipes_avail_cv_=false])
- AC_LANG_POP])
-
-if [test x$pipes_avail_cv_ = xtrue ]; then
- AC_DEFINE([HAVE_UNIX_PIPES], [1], [Whether UNIX pipes are available])
-fi
-
-# check for gmp
-AC_CACHE_CHECK(
- [if libgmp is available],
- [libgmp_avail_cv_],
- [libgmp_save_libs=$LIBS
- LIBS="-lgmp $LIBS"
- AC_LANG_PUSH(C++)
- AC_TRY_LINK(
- [#include <gmp.h>],
- [mpz_t bar;
- mpz_init(bar);
- mpz_clear(bar);],
- [libgmp_avail_cv_=true],
- [libgmp_avail_cv_=false])
- AC_LANG_POP
- LIBS=$libgmp_save_libs])
-
-if [test x$libgmp_avail_cv_ = xtrue ]; then
- AM_CONDITIONAL(HAVE_GMP, true)
- LIBS="-lgmp $LIBS"
-else
- AC_MSG_FAILURE("Could not find gmp library (set CPPFLAGS and LDFLAGS?)")
-fi
-
-# check for pcre
-AC_CACHE_CHECK(
- [if libpcre is available],
- [libpcre_avail_cv_],
- [libpcre_save_libs=$LIBS
- LIBS="-lpcre $LIBS"
- AC_LANG_PUSH(C++)
- AC_TRY_LINK(
- [#include <pcre.h>],
- [pcre_free((pcre *)NULL);],
- [libpcre_avail_cv_=true],
- [libpcre_avail_cv_=false])
- AC_LANG_POP
- LIBS=$libpcre_save_libs])
-
-if [test x$libpcre_avail_cv_ = xtrue ]; then
- AM_CONDITIONAL(HAVE_PCRE, true)
- LIBS="-lpcre $LIBS"
-else
- AC_MSG_FAILURE("Could not find pcre library (set CPPFLAGS and LDFLAGS?)")
-fi
-
-# check for expat or xmlparse
-AC_ARG_ENABLE(xml,
- [ --enable-xml Turn on support for XML parsing],
- [case "${enableval}" in
- yes) xml=true ;;
- no) xml=false ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-xml) ;;
- esac],[xml=true])
-AM_CONDITIONAL(USE_XML, test x$xml = xtrue)
-
-if [test x$xml = xtrue ]; then
- AC_CACHE_CHECK(
- [if libexpat is available],
- [libexpat_avail_cv_],
- [libexpat_save_libs=$LIBS
- LIBS="-lexpat $LIBS"
- AC_LANG_PUSH(C++)
- AC_TRY_LINK(
- [#include <stdio.h>
- extern "C" {
- #include <expat.h> // expat XML parser
- }],
- [XML_Parser parser = XML_ParserCreate(NULL);
- return parser != NULL;],
- [libexpat_avail_cv_=true],
- [libexpat_avail_cv_=false])
- AC_LANG_POP
- LIBS=$libexpat_save_libs])
-
- if [test x$libexpat_avail_cv_ = xtrue ]; then
- AM_CONDITIONAL(HAVE_EXPAT, true)
- LIBS="-lexpat $LIBS"
- else
- AM_CONDITIONAL(HAVE_EXPAT, false)
- fi
-else
- AM_CONDITIONAL(HAVE_EXPAT, false)
-fi
-
-if [test x$xml = xtrue ]; then
- if [test x$libexpat_avail_cv_ = xfalse ]; then
- AC_CACHE_CHECK(
- [if libxmlparse is available],
- [libxmlparse_avail_cv_],
- [libxmlparse_save_libs=$LIBS
- LIBS="-lxmlparse -lxmltok $LIBS"
- AC_LANG_PUSH(C++)
- AC_TRY_LINK(
- [#include <stdio.h>
- extern "C" {
- #include <xmlparse.h> // expat XML parser
- }],
- [XML_Parser parser = XML_ParserCreate(NULL);
- return parser != NULL;],
- [libxmlparse_avail_cv_=true],
- [libxmlparse_avail_cv_=false])
- AC_LANG_POP
- LIBS=$libxmlparse_save_libs])
-
- if [test x$libxmlparse_avail_cv_ = xtrue ]; then
- AM_CONDITIONAL(HAVE_XMLPARSE, true)
- LIBS="-lxmlparse -lxmltok $LIBS"
- else
- AM_CONDITIONAL(HAVE_XMLPARSE, false)
- fi
- else
- AM_CONDITIONAL(HAVE_XMLPARSE, false)
- fi
-else
- AM_CONDITIONAL(HAVE_XMLPARSE, false)
-fi
-
-# check for libofx
-AC_ARG_ENABLE(ofx,
- [ --enable-ofx Turn on support for OFX/OCF parsing],
- [case "${enableval}" in
- yes) ofx=true ;;
- no) ofx=false ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-ofx) ;;
- esac],[ofx=true])
-AM_CONDITIONAL(USE_OFX, test x$ofx = xtrue)
-
-if [test x$ofx = xtrue ]; then
- AC_CACHE_CHECK(
- [if libofx is available],
- [libofx_avail_cv_],
- [libofx_save_libs=$LIBS
- LIBS="-lofx $LIBS"
- AC_LANG_PUSH(C++)
- AC_TRY_LINK(
- [#include <libofx.h>],
- [ LibofxContextPtr libofx_context = libofx_get_new_context();],
- [libofx_avail_cv_=true],
- [libofx_avail_cv_=false])
- AC_LANG_POP
- LIBS=$libofx_save_libs])
-
- if [test x$libofx_avail_cv_ = xtrue ]; then
- AM_CONDITIONAL(HAVE_LIBOFX, true)
- LIBS="-lofx $LIBS"
- else
- AM_CONDITIONAL(HAVE_LIBOFX, false)
- fi
-else
- AM_CONDITIONAL(HAVE_LIBOFX, false)
-fi
-
-# check for Python
-AC_ARG_ENABLE(python,
- [ --enable-python Build the amounts library as a Python module],
- [case "${enableval}" in
- yes) python=true ;;
- no) python=false ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-python) ;;
- esac],[python=false])
-AM_CONDITIONAL(USE_PYTHON, test x$python = xtrue)
-
-if [test x$python = xtrue ]; then
- AM_PATH_PYTHON(2.2,, :)
- if [test "$PYTHON" != :]; then
- AC_CACHE_CHECK(
- [if boost_python is available],
- [boost_python_cpplib_avail_cv_],
- [boost_python_save_libs=$LIBS
- LIBS="-lboost_python -lpython$PYTHON_VERSION $LIBS"
- AC_LANG_PUSH(C++)
- AC_TRY_LINK(
- [#include <boost/python.hpp>
- using namespace boost::python;
- class foo {};
- BOOST_PYTHON_MODULE(samp) {
- class_< foo > ("foo") ;
- }],
- [return 0],
- [boost_python_cpplib_avail_cv_=true],
- [boost_python_cpplib_avail_cv_=false])
- AC_LANG_POP
- LIBS=$boost_python_save_libs])
- if [test x$boost_python_cpplib_avail_cv_ = xtrue ]; then
- AM_CONDITIONAL(HAVE_BOOST_PYTHON, true)
- LIBS="-lboost_python -lpython$PYTHON_VERSION $LIBS"
- else
- AM_CONDITIONAL(HAVE_BOOST_PYTHON, false)
- fi
- else
- AM_CONDITIONAL(HAVE_BOOST_PYTHON, false)
- fi
-else
- AM_CONDITIONAL(HAVE_BOOST_PYTHON, false)
-fi
-
-# Check for options
-AC_ARG_ENABLE(debug,
- [ --enable-debug Turn on debugging],
- [case "${enableval}" in
- yes) debug=true ;;
- no) debug=false ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
- esac],[debug=false])
-AM_CONDITIONAL(DEBUG, test x$debug = xtrue)
-
-# Checks for header files.
-AC_STDC_HEADERS
-AC_HAVE_HEADERS(sys/stat.h)
-
-# Checks for typedefs, structures, and compiler characteristics.
-AC_HEADER_STDBOOL
-AC_TYPE_SIZE_T
-AC_STRUCT_TM
-
-# Checks for library functions.
-#AC_FUNC_ERROR_AT_LINE
-AC_HEADER_STDC
-AC_CHECK_FUNCS([access mktime realpath stat strftime strptime getpwuid getpwnam])
-
-AC_CONFIG_FILES([Makefile])
-AC_OUTPUT
diff --git a/contrib/CSVReader.cs b/contrib/CSVReader.cs
new file mode 100644
index 00000000..a22eab06
--- /dev/null
+++ b/contrib/CSVReader.cs
@@ -0,0 +1,165 @@
+// This code is in the public domain. I can't remember where I found it on the Web, but it
+// didn't come with any license.
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+namespace CSVReader {
+
+ /// <summary>
+ /// A data-reader style interface for reading CSV files.
+ /// </summary>
+ public class CSVReader : IDisposable {
+
+ #region Private variables
+
+ private Stream stream;
+ private StreamReader reader;
+
+ #endregion
+
+ /// <summary>
+ /// Create a new reader for the given stream.
+ /// </summary>
+ /// <param name="s">The stream to read the CSV from.</param>
+ public CSVReader(Stream s) : this(s, null) { }
+
+ /// <summary>
+ /// Create a new reader for the given stream and encoding.
+ /// </summary>
+ /// <param name="s">The stream to read the CSV from.</param>
+ /// <param name="enc">The encoding used.</param>
+ public CSVReader(Stream s, Encoding enc) {
+
+ this.stream = s;
+ if (!s.CanRead) {
+ throw new CSVReaderException("Could not read the given CSV stream!");
+ }
+ reader = (enc != null) ? new StreamReader(s, enc) : new StreamReader(s);
+ }
+
+ /// <summary>
+ /// Creates a new reader for the given text file path.
+ /// </summary>
+ /// <param name="filename">The name of the file to be read.</param>
+ public CSVReader(string filename) : this(filename, null) { }
+
+ /// <summary>
+ /// Creates a new reader for the given text file path and encoding.
+ /// </summary>
+ /// <param name="filename">The name of the file to be read.</param>
+ /// <param name="enc">The encoding used.</param>
+ public CSVReader(string filename, Encoding enc)
+ : this(new FileStream(filename, FileMode.Open), enc) { }
+
+ /// <summary>
+ /// Returns the fields for the next row of CSV data (or null if at eof)
+ /// </summary>
+ /// <returns>A string array of fields or null if at the end of file.</returns>
+ public string[] GetCSVLine() {
+
+ string data = reader.ReadLine();
+ if (data == null) return null;
+ if (data.Length == 0) return new string[0];
+
+ ArrayList result = new ArrayList();
+
+ ParseCSVFields(result, data);
+
+ return (string[])result.ToArray(typeof(string));
+ }
+
+ // Parses the CSV fields and pushes the fields into the result arraylist
+ private void ParseCSVFields(ArrayList result, string data) {
+
+ int pos = -1;
+ while (pos < data.Length)
+ result.Add(ParseCSVField(data, ref pos));
+ }
+
+ // Parses the field at the given position of the data, modified pos to match
+ // the first unparsed position and returns the parsed field
+ private string ParseCSVField(string data, ref int startSeparatorPosition) {
+
+ if (startSeparatorPosition == data.Length-1) {
+ startSeparatorPosition++;
+ // The last field is empty
+ return "";
+ }
+
+ int fromPos = startSeparatorPosition + 1;
+
+ // Determine if this is a quoted field
+ if (data[fromPos] == '"') {
+ // If we're at the end of the string, let's consider this a field that
+ // only contains the quote
+ if (fromPos == data.Length-1) {
+ fromPos++;
+ return "\"";
+ }
+
+ // Otherwise, return a string of appropriate length with double quotes collapsed
+ // Note that FSQ returns data.Length if no single quote was found
+ int nextSingleQuote = FindSingleQuote(data, fromPos+1);
+ startSeparatorPosition = nextSingleQuote+1;
+ return data.Substring(fromPos+1, nextSingleQuote-fromPos-1).Replace("\"\"", "\"");
+ }
+
+ // The field ends in the next comma or EOL
+ int nextComma = data.IndexOf(',', fromPos);
+ if (nextComma == -1) {
+ startSeparatorPosition = data.Length;
+ return data.Substring(fromPos);
+ }
+ else {
+ startSeparatorPosition = nextComma;
+ return data.Substring(fromPos, nextComma-fromPos);
+ }
+ }
+
+ // Returns the index of the next single quote mark in the string
+ // (starting from startFrom)
+ private int FindSingleQuote(string data, int startFrom) {
+
+ int i = startFrom-1;
+ while (++i < data.Length)
+ if (data[i] == '"') {
+ // If this is a double quote, bypass the chars
+ if (i < data.Length-1 && data[i+1] == '"') {
+ i++;
+ continue;
+ }
+ else
+ return i;
+ }
+ // If no quote found, return the end value of i (data.Length)
+ return i;
+ }
+
+ /// <summary>
+ /// Disposes the CSVReader. The underlying stream is closed.
+ /// </summary>
+ public void Dispose() {
+ // Closing the reader closes the underlying stream, too
+ if (reader != null) reader.Close();
+ else if (stream != null)
+ stream.Close(); // In case we failed before the reader was constructed
+ GC.SuppressFinalize(this);
+ }
+ }
+
+
+ /// <summary>
+ /// Exception class for CSVReader exceptions.
+ /// </summary>
+ public class CSVReaderException : ApplicationException {
+
+ /// <summary>
+ /// Constructs a new exception object with the given message.
+ /// </summary>
+ /// <param name="message">The exception message.</param>
+ public CSVReaderException(string message) : base(message) { }
+ }
+}
diff --git a/contrib/Makefile b/contrib/Makefile
new file mode 100644
index 00000000..6e4d367a
--- /dev/null
+++ b/contrib/Makefile
@@ -0,0 +1,4 @@
+all: ParseCcStmt.exe
+
+ParseCcStmt.exe: ParseCcStmt.cs CSVReader.cs
+ gmcs -out:ParseCcStmt.exe ParseCcStmt.cs CSVReader.cs
diff --git a/contrib/ParseCcStmt.cs b/contrib/ParseCcStmt.cs
new file mode 100644
index 00000000..c9ad1d55
--- /dev/null
+++ b/contrib/ParseCcStmt.cs
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2003-2008, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+
+using CSVReader;
+
+/**
+ * @file ParseCcStmt.cs
+ *
+ * @brief Provides a .NET way to turn a CSV report into Ledger transactions.
+ *
+ * I use this code for converting the statements from my own credit card
+ * issuer. I realize it's strange for this to be in C#, but I wrote it
+ * during a phase of C# contracting. The code is solid enough now --
+ * and the Mono project is portable enough -- that I haven't seen the
+ * need to rewrite it into another language like Python.
+ */
+
+namespace JohnWiegley
+{
+ public class Posting
+ {
+ public DateTime Date;
+ public DateTime PostedDate;
+ public string Code;
+ public string Payee;
+ public Decimal Amount;
+ }
+
+ public interface IStatementConverter
+ {
+ List<Posting> ConvertRecords(Stream s);
+ }
+
+ public class ConvertGoldMasterCardStatement : IStatementConverter
+ {
+ public List<Posting> ConvertRecords(Stream s)
+ {
+ List<Posting> posts = new List<Posting>();
+
+ using (CSVReader.CSVReader csv = new CSVReader.CSVReader(s)) {
+ string[] fields;
+ while ((fields = csv.GetCSVLine()) != null) {
+ if (fields[0] == "POSTING DATE")
+ continue;
+
+ Posting post = new Posting();
+
+ post.Date = DateTime.ParseEpost(fields[0], "mm/dd/yy", null);
+ post.PostedDate = DateTime.ParseEpost(fields[1], "mm/dd/yy", null);
+ post.Payee = fields[2].Trim();
+ post.Code = fields[3].Trim();
+ post.Amount = Convert.ToDecimal(fields[4].Trim());
+
+ if (post.Code.Length == 0)
+ post.Code = null;
+
+ posts.Add(post);
+ }
+ }
+ return posts;
+ }
+ }
+
+ public class ConvertMastercardStatement : IStatementConverter
+ {
+ public List<Posting> ConvertRecords(Stream s)
+ {
+ List<Posting> posts = new List<Posting>();
+
+ using (CSVReader.CSVReader csv = new CSVReader.CSVReader(s)) {
+ string[] fields;
+ while ((fields = csv.GetCSVLine()) != null) {
+ Posting post = new Posting();
+
+ post.Date = DateTime.ParseEpost(fields[0], "m/dd/yyyy", null);
+ post.Payee = fields[2].Trim();
+ post.Code = fields[3].Trim();
+ post.Amount = - Convert.ToDecimal(fields[4].Trim());
+
+ if (post.Code.Length == 0)
+ post.Code = null;
+
+ posts.Add(post);
+ }
+ }
+ return posts;
+ }
+ }
+
+ public class PrintPostings
+ {
+ public string DefaultAccount(Posting post) {
+ if (Regex.IsMatch(post.Payee, "IGA"))
+ return "Expenses:Food";
+ return "Expenses:Food";
+ }
+
+ public void Print(string AccountName, string PayAccountName,
+ List<Posting> posts)
+ {
+ foreach (Posting post in posts) {
+ if (post.Amount < 0) {
+ Console.WriteLine("{0} * {1}{2}", post.Date.ToString("yyyy/mm/dd"),
+ post.Code != null ? "(" + post.Code + ") " : "",
+ post.Payee);
+ Console.WriteLine(" {0,-36}{1,12}", AccountName,
+ "$" + (- post.Amount).ToString());
+ Console.WriteLine(" {0}", PayAccountName);
+ } else {
+ Console.WriteLine("{0} {1}{2}", post.Date.ToString("yyyy/mm/dd"),
+ post.Code != null ? "(" + post.Code + ") " : "",
+ post.Payee);
+ Console.WriteLine(" {0,-36}{1,12}", DefaultAccount(post),
+ "$" + post.Amount.ToString());
+ Console.WriteLine(" * {0}", AccountName);
+ }
+ Console.WriteLine();
+ }
+ }
+ }
+
+ public class ParseCcStmt
+ {
+ public static int Main(string[] args)
+ {
+ StreamReader reader = new StreamReader(args[0]);
+ string firstLine = reader.ReadLine();
+
+ string CardAccount = args[1];
+ string BankAccount = args[2];
+
+ IStatementConverter converter;
+
+ if (firstLine.StartsWith("POSTING DATE")) {
+ converter = new ConvertGoldMasterCardStatement();
+ } else {
+ converter = new ConvertMastercardStatement();
+ }
+
+ reader = new StreamReader(args[0]);
+ List<Posting> posts = converter.ConvertRecords(reader.BaseStream);
+
+ PrintPostings printer = new PrintPostings();
+ printer.Print(CardAccount, BankAccount, posts);
+
+ return 0;
+ }
+ }
+}
diff --git a/scripts/README b/contrib/README
index 6108afbf..6108afbf 100644
--- a/scripts/README
+++ b/contrib/README
diff --git a/scripts/bal b/contrib/bal
index 423e3e41..423e3e41 100755
--- a/scripts/bal
+++ b/contrib/bal
diff --git a/scripts/bal-huquq b/contrib/bal-huquq
index fad2854a..fad2854a 100755
--- a/scripts/bal-huquq
+++ b/contrib/bal-huquq
diff --git a/scripts/entry b/contrib/entry
index cc030d8e..ef1869da 100755
--- a/scripts/entry
+++ b/contrib/entry
@@ -6,11 +6,11 @@ fi
line=`wc -l $LEDGER | awk '{print $1}'`
-if ledger entry "$@" > /tmp/entry; then
- cat /tmp/entry >> $LEDGER
+if ledger xact "$@" > /tmp/xact; then
+ cat /tmp/xact >> $LEDGER
else
echo "$@" >> $LEDGER
fi
-rm /tmp/entry
+rm /tmp/xact
vi +$line $LEDGER
diff --git a/contrib/getquote-uk.py b/contrib/getquote-uk.py
new file mode 100755
index 00000000..a69d4e7d
--- /dev/null
+++ b/contrib/getquote-uk.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import urllib, string, sys
+
+def download(sym):
+ url = "http://uk.old.finance.yahoo.com/d/quotes.csv?s="
+ url += sym + "&f=sl1d1t1c1ohgv&e=.csv"
+ f = urllib.urlopen(url, proxies={})
+ info = f.read()
+ f.close()
+ fields = string.split(info, ',')
+ result = float(fields[1])/100
+ return result
+
+
+sym = sys.argv[1]
+sym = sym.replace('_', '.')
+if sym == '£':
+ print '£1.00'
+else:
+ try: print "£" +str(download(sym))
+ except: pass
diff --git a/scripts/getquote b/contrib/getquote.pl
index bed561d6..8e3bb678 100755
--- a/scripts/getquote
+++ b/contrib/getquote.pl
@@ -1,8 +1,9 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
$timeout = 60;
use Finance::Quote;
+use POSIX qw(strftime localtime time);
$q = Finance::Quote->new;
$q->timeout($timeout);
@@ -10,6 +11,8 @@ $q->require_labels(qw/price/);
%quotes = $q->fetch("nasdaq", $ARGV[0]);
if ($quotes{$ARGV[0], "price"}) {
+ print strftime('%Y/%m/%d %H:%M:%S', localtime(time()));
+ print " ", $ARGV[0], " ";
print "\$", $quotes{$ARGV[0], "price"}, "\n";
} else {
exit 1;
diff --git a/scripts/ledger-du b/contrib/ledger-du
index f5d7dd7d..580e916e 100755
--- a/scripts/ledger-du
+++ b/contrib/ledger-du
@@ -23,14 +23,14 @@ def report_file(path):
print
def find_files(path):
- entries = os.listdir(path)
- for entry in entries:
- entry = join(path, entry)
- if not islink(entry):
- if isdir(entry) and entry != "/proc":
- find_files(entry)
+ xacts = os.listdir(path)
+ for xact in xacts:
+ xact = join(path, xact)
+ if not islink(xact):
+ if isdir(xact) and xact != "/proc":
+ find_files(xact)
else:
- report_file(entry)
+ report_file(xact)
args = sys.argv[1:]
if len(args):
diff --git a/contrib/repl.sh b/contrib/repl.sh
new file mode 100755
index 00000000..42fb54c6
--- /dev/null
+++ b/contrib/repl.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+EXEC=$(which ledger)
+if [[ -z "$EXEC" ]]; then
+ EXEC=$HOME/Products/ledger/ledger
+fi
+
+if [[ ! -x "$EXEC" ]]; then
+ echo Cannot find Ledger executable
+ exit 1
+fi
+
+LESS=--quit-if-one-screen exec $EXEC --pager less "$@"
diff --git a/scripts/report b/contrib/report
index 24418cdc..24418cdc 100755
--- a/scripts/report
+++ b/contrib/report
diff --git a/scripts/tc b/contrib/tc
index c24be99a..c24be99a 100755
--- a/scripts/tc
+++ b/contrib/tc
diff --git a/scripts/ti b/contrib/ti
index a7214e65..a7214e65 100755
--- a/scripts/ti
+++ b/contrib/ti
diff --git a/scripts/to b/contrib/to
index 3198db3c..3198db3c 100755
--- a/scripts/to
+++ b/contrib/to
diff --git a/scripts/trend b/contrib/trend
index 3c189c0b..3c189c0b 100755
--- a/scripts/trend
+++ b/contrib/trend
diff --git a/contrib/vim/README b/contrib/vim/README
new file mode 100644
index 00000000..4da73ea6
--- /dev/null
+++ b/contrib/vim/README
@@ -0,0 +1,100 @@
+
+This is the ledger filetype for vim.
+Copy each file to the corresponding directory in your ~/.vim directory.
+Then include the following line in your .vimrc or in ~/.vim/filetype.vim
+ au BufNewFile,BufRead *.ldg,*.ledger setf ledger
+You can also use a modeline like this in every ledger file
+ vim:filetype=ledger
+
+Configuration
+======================================================================
+Include the following let-statements somewhere in your .vimrc
+to modify the behaviour of the ledger filetype.
+
+* Number of colums that will be used to display the foldtext.
+ Set this when you think that the amount is too far off to the right.
+ let g:ledger_maxwidth = 80
+
+* String that will be used to fill the space between account name
+ and amount in the foldtext. Set this to get some kind of lines
+ or visual aid.
+ let g:ledger_fillstring = ' -'
+ My special tip is to use so-called digraphs:
+ Press <C-K> followed by the two-characters key sequence below.
+ (in insert-mode)
+ '. = ˙ or ': = ¨ --> ˙˙˙˙˙˙ or ¨¨¨¨¨¨
+ ', = ¸ --> ¸¸¸¸¸¸
+ .M = · --> ······
+ >> = » --> »»»»»»
+ All those look rather unobstrusive
+ and provide a good visual aid to find the correct amount.
+
+* If you want the account completion to be sorted by level of detail/depth
+ instead of alphabetical, include the following line:
+ let g:ledger_detailed_first = 1
+
+Completion
+======================================================================
+Omni completion is implemented for account names and tags.
+
+Accounts
+----------------------------------------------------------------------
+Account names are matched by the start of every sub-level.
+When you insert an account name like this:
+ Asse<C-X><C-O>
+You will get a list of top-level accounts that start like this.
+
+Go ahead and try something like:
+ As:Ban:Che<C-X><C-O>
+When you have an account like this, 'Assets:Bank:Checking' should show up.
+
+When you want to complete on a virtual transaction,
+it's currently best to keep the cursor in front of the closing bracket.
+Of course you can insert the closing bracket after calling the completion, too.
+
+Tags
+----------------------------------------------------------------------
+The support for completing tags is pretty basic right now
+but it's useful to keep the spelling of your tags consistent.
+You can call the completion after the ';' to get a list of all tags.
+When you have a list of tags (:like: :this:) you can call
+the completion too and everything up to the last ':' (excluding whitespace)
+will be considered the beginning of the tag to search for.
+
+Revision history (major changes)
+======================================================================
+ 2009-06-23 & 2009-06-25
+ J. Klähn: Omni-Completion for account names and tags
+ 2009-06-17 J. Klähn: Highlight account text
+ Updated documentation and added fillstring option.
+ 2009-06-15 J. Klähn: Split into multiple files
+ 2009-06-12 J. Klähn: Use all available columns for foldtext
+ Also rewrote foldtext generation.
+ 2009-03-25 J. Klähn: Allow Metadata
+ in transactions and postings (Ledger 3.0)
+ Also fixed alignment for multi-byte-characters
+ 2009-01-28 S.Karrmann: minor fixes
+ 2009-01-27 third version by S.Karrmann.
+ better extraction of the amount of the posting
+ decimal separator can be one of '.' and ','.
+ 2005-02-05 first version (partly copied from ledger.vim 0.0.1)
+
+License
+======================================================================
+Copyright 2009 by Johann Klähn
+Copyright 2009 by Stefan Karrmann
+Copyright 2005 by Wolfgang Oertl
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
diff --git a/contrib/vim/ftplugin/ledger.vim b/contrib/vim/ftplugin/ledger.vim
new file mode 100644
index 00000000..d75a6869
--- /dev/null
+++ b/contrib/vim/ftplugin/ledger.vim
@@ -0,0 +1,302 @@
+" Vim filetype plugin file
+" filetype: ledger
+" Version: 0.1.0
+" by Johann Klähn; Use according to the terms of the GPL>=2.
+" vim:ts=2:sw=2:sts=2:foldmethod=marker
+
+if exists("b:did_ftplugin")
+ finish
+endif
+
+let b:did_ftplugin = 1
+
+let b:undo_ftplugin = "setlocal ".
+ \ "foldmethod< foldtext< ".
+ \ "include< comments< omnifunc< "
+
+" don't fill fold lines --> cleaner look
+setl fillchars="fold: "
+setl foldtext=LedgerFoldText()
+setl foldmethod=syntax
+setl include=^!include
+setl comments=b:;
+setl omnifunc=LedgerComplete
+
+" You can set a maximal number of columns the fold text (excluding amount)
+" will use by overriding g:ledger_maxwidth in your .vimrc.
+" When maxwidth is zero, the amount will be displayed at the far right side
+" of the screen.
+if !exists('g:ledger_maxwidth')
+ let g:ledger_maxwidth = 0
+endif
+
+if !exists('g:ledger_fillstring')
+ let g:ledger_fillstring = ' '
+endif
+
+" If enabled this will list the most detailed matches at the top {{{
+" of the completion list.
+" For example when you have some accounts like this:
+" A:Ba:Bu
+" A:Bu:Bu
+" and you complete on A:B:B normal behaviour may be the following
+" A:B:B
+" A:Bu:Bu
+" A:Bu
+" A:Ba:Bu
+" A:Ba
+" A
+" with this option turned on it will be
+" A:B:B
+" A:Bu:Bu
+" A:Ba:Bu
+" A:Bu
+" A:Ba
+" A
+" }}}
+if !exists('g:ledger_detailed_first')
+ let g:ledger_detailed_first = 0
+endif
+
+let s:rx_amount = '\('.
+ \ '\%([0-9]\+\)'.
+ \ '\%([,.][0-9]\+\)*'.
+ \ '\|'.
+ \ '[,.][0-9]\+'.
+ \ '\)'.
+ \ '\s*\%([[:alpha:]¢$€£]\+\s*\)\?'.
+ \ '\%(\s*;.*\)\?$'
+
+function! LedgerFoldText() "{{{1
+ " find amount
+ let amount = ""
+ let lnum = v:foldstart
+ while lnum <= v:foldend
+ let line = getline(lnum)
+
+ " Skip metadata/leading comment
+ if line !~ '^\%(\s\+;\|\d\)'
+ " No comment, look for amount...
+ let groups = matchlist(line, s:rx_amount)
+ if ! empty(groups)
+ let amount = groups[1]
+ break
+ endif
+ endif
+ let lnum += 1
+ endwhile
+
+ let fmt = '%s %s '
+ " strip whitespace at beginning and end of line
+ let foldtext = substitute(getline(v:foldstart),
+ \ '\(^\s\+\|\s\+$\)', '', 'g')
+
+ " number of columns foldtext can use
+ let columns = s:get_columns(0)
+ if g:ledger_maxwidth
+ let columns = min([columns, g:ledger_maxwidth])
+ endif
+ let columns -= s:multibyte_strlen(printf(fmt, '', amount))
+
+ " add spaces so the text is always long enough when we strip it
+ " to a certain width (fake table)
+ if strlen(g:ledger_fillstring)
+ " add extra spaces so fillstring aligns
+ let filen = s:multibyte_strlen(g:ledger_fillstring)
+ let folen = s:multibyte_strlen(foldtext)
+ let foldtext .= repeat(' ', filen - (folen%filen))
+
+ let foldtext .= repeat(g:ledger_fillstring,
+ \ s:get_columns(0)/filen)
+ else
+ let foldtext .= repeat(' ', s:get_columns(0))
+ endif
+
+ " we don't use slices[:5], because that messes up multibyte characters
+ let foldtext = substitute(foldtext, '.\{'.columns.'}\zs.*$', '', '')
+
+ return printf(fmt, foldtext, amount)
+endfunction "}}}
+
+function! LedgerComplete(findstart, base) "{{{1
+ if a:findstart
+ let lnum = line('.')
+ let line = getline('.')
+ let lastcol = col('.') - 2
+ if line =~ '^\d' "{{{2 (date / payee / description)
+ let b:compl_context = 'payee'
+ return -1
+ elseif line =~ '^\s\+;' "{{{2 (metadata / tags)
+ let b:compl_context = 'meta-tag'
+ let first_possible = matchend(line, '^\s\+;')
+
+ " find first column of text to be replaced
+ let firstcol = lastcol
+ while firstcol >= 0
+ if firstcol <= first_possible
+ " Stop before the ';' don't ever include it
+ let firstcol = first_possible
+ break
+ elseif line[firstcol] =~ ':'
+ " Stop before first ':'
+ let firstcol += 1
+ break
+ endif
+
+ let firstcol -= 1
+ endwhile
+
+ " strip whitespace starting from firstcol
+ let end_of_whitespace = matchend(line, '^\s\+', firstcol)
+ if end_of_whitespace != -1
+ let firstcol = end_of_whitespace
+ endif
+
+ return firstcol
+ elseif line =~ '^\s\+' "{{{2 (account)
+ let b:compl_context = 'account'
+ if matchend(line, '^\s\+\%(\S \S\|\S\)\+') <= lastcol
+ " only allow completion when in or at end of account name
+ return -1
+ endif
+ " the start of the first non-blank character
+ " (excluding virtual-transaction-marks)
+ " is the beginning of the account name
+ return matchend(line, '^\s\+[\[(]\?')
+ else "}}}
+ return -1
+ endif
+ else
+ if b:compl_context == 'account' "{{{2 (account)
+ unlet! b:compl_context
+ let hierarchy = split(a:base, ':')
+ if a:base =~ ':$'
+ call add(hierarchy, '')
+ endif
+
+ let results = LedgerFindInTree(LedgerGetAccountHierarchy(), hierarchy)
+ " sort by alphabet and reverse because it will get reversed one more time
+ let results = reverse(sort(results))
+ if g:ledger_detailed_first
+ let results = sort(results, 's:sort_accounts_by_depth')
+ endif
+ call add(results, a:base)
+ return reverse(results)
+ elseif b:compl_context == 'meta-tag' "{{{2
+ unlet! b:compl_context
+ let results = [a:base]
+ call extend(results, sort(s:filter_items(keys(LedgerGetTags()), a:base)))
+ return results
+ else "}}}
+ unlet! b:compl_context
+ return []
+ endif
+ endif
+endf "}}}
+
+function! LedgerFindInTree(tree, levels) "{{{1
+ if empty(a:levels)
+ return []
+ endif
+ let results = []
+ let currentlvl = a:levels[0]
+ let nextlvls = a:levels[1:]
+ let branches = s:filter_items(keys(a:tree), currentlvl)
+ for branch in branches
+ call add(results, branch)
+ if !empty(nextlvls)
+ for result in LedgerFindInTree(a:tree[branch], nextlvls)
+ call add(results, branch.':'.result)
+ endfor
+ endif
+ endfor
+ return results
+endf "}}}
+
+function! LedgerGetAccountHierarchy() "{{{1
+ let hierarchy = {}
+ let accounts = s:grep_buffer('^\s\+\zs[^[:blank:];]\%(\S \S\|\S\)\+\ze')
+ for name in accounts
+ " remove virtual-transaction-marks
+ let name = substitute(name, '\%(^\s*[\[(]\?\|[\])]\?\s*$\)', '', 'g')
+ let last = hierarchy
+ for part in split(name, ':')
+ let last[part] = get(last, part, {})
+ let last = last[part]
+ endfor
+ endfor
+ return hierarchy
+endf "}}}
+
+function! LedgerGetTags() "{{{1
+ let alltags = {}
+ let metalines = s:grep_buffer('^\s\+;\s*\zs.*$')
+ for line in metalines
+ " (spaces at beginning are stripped by matchstr!)
+ if line[0] == ':'
+ " multiple tags
+ for val in split(line, ':')
+ if val !~ '^\s*$'
+ let name = s:strip_spaces(val)
+ let alltags[name] = get(alltags, name, [])
+ endif
+ endfor
+ elseif line =~ '^.*:.*$'
+ " line with tag=value
+ let name = s:strip_spaces(split(line, ':')[0])
+ let val = s:strip_spaces(join(split(line, ':')[1:], ':'))
+ let values = get(alltags, name, [])
+ call add(values, val)
+ let alltags[name] = values
+ endif
+ endfor
+ return alltags
+endf "}}}
+
+" Helper functions {{{1
+
+" return length of string with fix for multibyte characters
+function! s:multibyte_strlen(text) "{{{2
+ return strlen(substitute(a:text, ".", "x", "g"))
+endfunction "}}}
+
+" get # of visible/usable columns in current window
+function! s:get_columns(win) "{{{2
+ " As long as vim doesn't provide a command natively,
+ " we have to compute the available columns.
+ " see :help todo.txt -> /Add argument to winwidth()/
+ " FIXME: Although this will propably never be used with debug mode enabled
+ " this should take the signs column into account (:help sign.txt)
+ let columns = (winwidth(a:win) == 0 ? 80 : winwidth(a:win)) - &foldcolumn
+ if &number
+ " line('w$') is the line number of the last line
+ let columns -= max([len(line('w$'))+1, &numberwidth])
+ endif
+ return columns
+endfunction "}}}
+
+" remove spaces at start and end of string
+function! s:strip_spaces(text) "{{{2
+ return matchstr(a:text, '^\s*\zs\S\%(.*\S\)\?\ze\s*$')
+endf "}}}
+
+" return only those items that start with a specified keyword
+function! s:filter_items(list, keyword) "{{{2
+ return filter(a:list, 'v:val =~ ''^\V'.substitute(a:keyword, '\\', '\\\\', 'g').'''')
+endf "}}}
+
+" return all lines matching an expression, returning only the matched part
+function! s:grep_buffer(expression) "{{{2
+ let lines = map(getline(1, '$'), 'matchstr(v:val, '''.a:expression.''')')
+ return filter(lines, 'v:val != ""')
+endf "}}}
+
+function! s:sort_accounts_by_depth(name1, name2) "{{{2
+ let depth1 = s:count_expression(a:name1, ':')
+ let depth2 = s:count_expression(a:name2, ':')
+ return depth1 == depth2 ? 0 : depth1 > depth2 ? 1 : -1
+endf "}}}
+
+function! s:count_expression(text, expression) "{{{2
+ return len(split(a:text, a:expression, 1))-1
+endf "}}}
diff --git a/contrib/vim/syntax/ledger.vim b/contrib/vim/syntax/ledger.vim
new file mode 100644
index 00000000..8914cf2a
--- /dev/null
+++ b/contrib/vim/syntax/ledger.vim
@@ -0,0 +1,49 @@
+" Vim syntax file
+" filetype: ledger
+" Version: 0.1.0
+" by Johann Klähn; Use according to the terms of the GPL>=2.
+" by Stefan Karrmann; Use according to the terms of the GPL>=2.
+" by Wolfgang Oertl; Use according to the terms of the GPL>=2.
+" Revision history
+" 2009-06-12 J. Klähn: Use all available columns for foldtext
+" 2009-03-25 J. Klähn: Allow Metadata
+" in transactions and postings (Ledger 3.0)
+" Also fixed alignment for multi-byte-characters
+" 2009-01-28 S.Karrmann: minor fixes
+" 2009-01-27 third version by S.Karrmann.
+" better extraction of the amount of the posting
+" decimal separator can be one of '.' and ','.
+" 2005-02-05 first version (partly copied from ledger.vim 0.0.1)
+" vim:ts=2:sw=2:sts=2:foldmethod=marker
+
+if version < 600
+ syntax clear
+elseif exists("b:current_sytax")
+ finish
+endif
+
+" for debugging
+syntax clear
+
+" region: a transaction containing postings
+syn region transNorm start=/^[[:digit:]~]/ skip=/^\s/ end=/^/
+ \ fold keepend transparent contains=transDate, Metadata, Posting
+syn match transDate /^\d\S\+/ contained
+syn match Metadata /^\s\+;.*/ contained
+syn match Comment /^;.*$/
+" every space in an account name shall be surrounded by two non-spaces
+" every account name ends with a tab, two spaces or the end of the line
+syn match Account /^\s\+\zs\%(\S \S\|\S\)\+\ze\%([ ]\{2,}\|\t\s*\|\s*$\)/ contained
+syn match Posting /^\s\+[^[:blank:];].*$/ contained transparent contains=Account
+
+
+highlight default link transDate Question
+highlight default link Metadata PreProc
+highlight default link Comment Comment
+highlight default link Account Identifier
+
+" syncinc is easy: search for the first transaction.
+syn sync clear
+syn sync match ledgerSync grouphere transNorm "^\d"
+
+let b:current_syntax = "ledger"
diff --git a/csv.cc b/csv.cc
deleted file mode 100644
index 4a8c1157..00000000
--- a/csv.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-#include "csv.h"
-
-namespace ledger {
-
-namespace {
- inline void write_escaped_string(std::ostream& out, const std::string& xact)
- {
- out << "\"";
- for (std::string::const_iterator i = xact.begin(); i != xact.end(); i++)
- if (*i == '"') {
- out << "\\";
- out << "\"";
- } else {
- out << *i;
- }
- out << "\"";
- }
-}
-
-void format_csv_transactions::operator()(transaction_t& xact)
-{
- if (! transaction_has_xdata(xact) ||
- ! (transaction_xdata_(xact).dflags & TRANSACTION_DISPLAYED)) {
-
- {
- format_t fmt("%D");
- std::ostringstream str;
- fmt.format(str, details_t(xact));
- write_escaped_string(out, str.str());
- }
- out << ',';
-
- {
- format_t fmt("%P");
- std::ostringstream str;
- fmt.format(str, details_t(xact));
- write_escaped_string(out, str.str());
- }
- out << ',';
-
- {
- format_t fmt("%A");
- std::ostringstream str;
- fmt.format(str, details_t(xact));
- write_escaped_string(out, str.str());
- }
- out << ',';
-
- {
- format_t fmt("%t");
- std::ostringstream str;
- fmt.format(str, details_t(xact));
- write_escaped_string(out, str.str());
- }
- out << ',';
-
- {
- format_t fmt("%T");
- std::ostringstream str;
- fmt.format(str, details_t(xact));
- write_escaped_string(out, str.str());
- }
- out << ',';
-
- switch (xact.state) {
- case transaction_t::CLEARED:
- write_escaped_string(out, "*");
- break;
- case transaction_t::PENDING:
- write_escaped_string(out, "!");
- break;
- default: {
- transaction_t::state_t state;
- if (xact.entry->get_state(&state))
- switch (state) {
- case transaction_t::CLEARED:
- write_escaped_string(out, "*");
- break;
- case transaction_t::PENDING:
- write_escaped_string(out, "!");
- break;
- default:
- write_escaped_string(out, "");
- break;
- }
- }
- }
- out << ',';
-
- write_escaped_string(out, xact.entry->code);
- out << ',';
-
- {
- format_t fmt("%N");
- std::ostringstream str;
- fmt.format(str, details_t(xact));
- write_escaped_string(out, str.str());
- }
- out << '\n';
-
- transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED;
- }
-}
-
-} // namespace ledger
diff --git a/csv.h b/csv.h
deleted file mode 100644
index 3b370631..00000000
--- a/csv.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _CSV_H
-#define _CSV_H
-
-#include "journal.h"
-#include "format.h"
-
-namespace ledger {
-
-class format_csv_transactions : public item_handler<transaction_t>
-{
- protected:
- std::ostream& out;
-
- public:
- format_csv_transactions(std::ostream& _out) : out(_out) {}
- virtual void flush() {
- out.flush();
- }
- virtual void operator()(transaction_t& xact);
-};
-
-} // namespace ledger
-
-#endif // _REPORT_H
diff --git a/data b/data
deleted file mode 160000
-Subproject e4eb5c28c80b799762139c700ada3f5681b72cc
diff --git a/datetime.cc b/datetime.cc
deleted file mode 100644
index 2b9ddddf..00000000
--- a/datetime.cc
+++ /dev/null
@@ -1,372 +0,0 @@
-#if defined(__GNUG__) && __GNUG__ < 3
-#define _XOPEN_SOURCE
-#endif
-
-#include "debug.h"
-#include "datetime.h"
-
-#include <ctime>
-#include <cctype>
-#include <climits>
-#include <cstdlib>
-
-date_t date_t::now(std::time(NULL));
-int date_t::current_year = date_t::now.year();
-std::string date_t::input_format;
-std::string date_t::output_format = "%Y/%m/%d";
-
-const char * date_t::formats[] = {
- "%y/%m/%d",
- "%Y/%m/%d",
- "%m/%d",
- "%y.%m.%d",
- "%Y.%m.%d",
- "%m.%d",
- "%y-%m-%d",
- "%Y-%m-%d",
- "%m-%d",
- "%a",
- "%A",
- "%b",
- "%B",
- "%Y",
- NULL
-};
-
-datetime_t datetime_t::now(std::time(NULL));
-
-namespace {
- static std::time_t base = -1;
- static int base_year = -1;
-
- static const int month_days[12] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
-
- bool parse_date_mask(const char * date_str, struct std::tm * result);
- bool parse_date(const char * date_str, std::time_t * result,
- const int year = -1);
- bool quick_parse_date(const char * date_str, std::time_t * result);
-}
-
-date_t::date_t(const std::string& _when)
-{
- if (! quick_parse_date(_when.c_str(), &when))
- throw new date_error
- (std::string("Invalid date string: ") + _when);
-}
-
-datetime_t::datetime_t(const std::string& _when)
-{
- if (const char * p = std::strchr(_when.c_str(), ' ')) {
- date_t date(std::string(_when, 0, p - _when.c_str()));
-
- struct std::tm moment = *std::localtime(&date.when);
- if (! strptime(++p, "%H:%M:%S", &moment))
- throw new datetime_error
- (std::string("Invalid date/time string: ") + _when);
-
- when = std::mktime(&moment);
- } else {
- when = date_t(_when).when;
- }
-}
-
-datetime_t interval_t::first(const datetime_t& moment) const
-{
- datetime_t quant(begin);
-
- if (moment && moment > quant) {
- // Find an efficient starting point for the upcoming while loop.
- // We want a date early enough that the range will be correct, but
- // late enough that we don't spend hundreds of thousands of loops
- // skipping through time.
-
- struct std::tm * desc = std::localtime(&moment.when);
-
- if (years)
- desc->tm_mon = 0;
- desc->tm_mday = 1;
-
- desc->tm_hour = 0;
- desc->tm_min = 0;
- desc->tm_sec = 0;
- desc->tm_isdst = -1;
-
- quant = std::mktime(desc);
-
- datetime_t temp;
- while (moment >= (temp = increment(quant))) {
- if (quant == temp)
- break;
- quant = temp;
- }
- }
-
- return quant;
-}
-
-datetime_t interval_t::increment(const datetime_t& moment) const
-{
- struct std::tm * desc = std::localtime(&moment.when);
-
- if (years)
- desc->tm_year += years;
- if (months)
- desc->tm_mon += months;
- if (days)
- desc->tm_mday += days;
-
- desc->tm_hour += hours;
- desc->tm_min += minutes;
- desc->tm_sec += seconds;
-
- desc->tm_isdst = -1;
-
- return std::mktime(desc);
-}
-
-namespace {
- void parse_inclusion_specifier(const std::string& word,
- datetime_t * begin, datetime_t * end)
- {
- struct std::tm when;
-
- if (! parse_date_mask(word.c_str(), &when))
- throw new datetime_error(std::string("Could not parse date mask: ") + word);
-
- when.tm_hour = 0;
- when.tm_min = 0;
- when.tm_sec = 0;
- when.tm_isdst = -1;
-
- bool saw_year = true;
- bool saw_mon = true;
- bool saw_day = true;
-
- if (when.tm_year == -1) {
- when.tm_year = date_t::current_year - 1900;
- saw_year = false;
- }
- if (when.tm_mon == -1) {
- when.tm_mon = 0;
- saw_mon = false;
- } else {
- saw_year = false; // don't increment by year if month used
- }
- if (when.tm_mday == -1) {
- when.tm_mday = 1;
- saw_day = false;
- } else {
- saw_mon = false; // don't increment by month if day used
- saw_year = false; // don't increment by year if day used
- }
-
- if (begin) {
- *begin = std::mktime(&when);
- assert(int(*begin) != -1);
- if (end) {
- *end = interval_t(saw_day ? 1 : 0, saw_mon ? 1 : 0,
- saw_year ? 1 : 0).increment(*begin);
- assert(int(*end) != -1);
- }
- }
- else if (end) {
- *end = std::mktime(&when);
- assert(int(*end) != -1);
- }
- }
-
- inline void read_lower_word(std::istream& in, std::string& word) {
- in >> word;
- for (int i = 0, l = word.length(); i < l; i++)
- word[i] = std::tolower(word[i]);
- }
-
- void parse_date_words(std::istream& in, std::string& word,
- datetime_t * begin, datetime_t * end)
- {
- std::string type;
-
- bool mon_spec = false;
- char buf[32];
-
- if (word == "this" || word == "last" || word == "next") {
- type = word;
- if (! in.eof())
- read_lower_word(in, word);
- else
- word = "month";
- } else {
- type = "this";
- }
-
- if (word == "month") {
- std::strftime(buf, 31, "%B", datetime_t::now.localtime());
- word = buf;
- mon_spec = true;
- }
- else if (word == "year") {
- std::strftime(buf, 31, "%Y", datetime_t::now.localtime());
- word = buf;
- }
-
- parse_inclusion_specifier(word, begin, end);
-
- if (type == "last") {
- if (mon_spec) {
- if (begin)
- *begin = interval_t(0, -1, 0).increment(*begin);
- if (end)
- *end = interval_t(0, -1, 0).increment(*end);
- } else {
- if (begin)
- *begin = interval_t(0, 0, -1).increment(*begin);
- if (end)
- *end = interval_t(0, 0, -1).increment(*end);
- }
- }
- else if (type == "next") {
- if (mon_spec) {
- if (begin)
- *begin = interval_t(0, 1, 0).increment(*begin);
- if (end)
- *end = interval_t(0, 1, 0).increment(*end);
- } else {
- if (begin)
- *begin = interval_t(0, 0, 1).increment(*begin);
- if (end)
- *end = interval_t(0, 0, 1).increment(*end);
- }
- }
- }
-}
-
-void interval_t::parse(std::istream& in)
-{
- std::string word;
-
- while (! in.eof()) {
- read_lower_word(in, word);
- if (word == "every") {
- read_lower_word(in, word);
- if (std::isdigit(word[0])) {
- int quantity = std::atol(word.c_str());
- read_lower_word(in, word);
- if (word == "days")
- days = quantity;
- else if (word == "weeks")
- days = 7 * quantity;
- else if (word == "months")
- months = quantity;
- else if (word == "quarters")
- months = 3 * quantity;
- else if (word == "years")
- years = quantity;
- else if (word == "hours")
- hours = quantity;
- else if (word == "minutes")
- minutes = quantity;
- else if (word == "seconds")
- seconds = quantity;
- }
- else if (word == "day")
- days = 1;
- else if (word == "week")
- days = 7;
- else if (word == "month")
- months = 1;
- else if (word == "quarter")
- months = 3;
- else if (word == "year")
- years = 1;
- else if (word == "hour")
- hours = 1;
- else if (word == "minute")
- minutes = 1;
- else if (word == "second")
- seconds = 1;
- }
- else if (word == "daily")
- days = 1;
- else if (word == "weekly")
- days = 7;
- else if (word == "biweekly")
- days = 14;
- else if (word == "monthly")
- months = 1;
- else if (word == "bimonthly")
- months = 2;
- else if (word == "quarterly")
- months = 3;
- else if (word == "yearly")
- years = 1;
- else if (word == "hourly")
- hours = 1;
- else if (word == "this" || word == "last" || word == "next") {
- parse_date_words(in, word, &begin, &end);
- }
- else if (word == "in") {
- read_lower_word(in, word);
- parse_date_words(in, word, &begin, &end);
- }
- else if (word == "from" || word == "since") {
- read_lower_word(in, word);
- parse_date_words(in, word, &begin, NULL);
- }
- else if (word == "to" || word == "until") {
- read_lower_word(in, word);
- parse_date_words(in, word, NULL, &end);
- }
- else {
- parse_inclusion_specifier(word, &begin, &end);
- }
- }
-}
-
-namespace {
- bool parse_date_mask(const char * date_str, struct std::tm * result)
- {
- if (! date_t::input_format.empty()) {
- std::memset(result, -1, sizeof(struct std::tm));
- if (strptime(date_str, date_t::input_format.c_str(), result))
- return true;
- }
- for (const char ** f = date_t::formats; *f; f++) {
- std::memset(result, -1, sizeof(struct std::tm));
- if (strptime(date_str, *f, result))
- return true;
- }
- return false;
- }
-
- bool parse_date(const char * date_str, std::time_t * result, const int year)
- {
- struct std::tm when;
-
- if (! parse_date_mask(date_str, &when))
- return false;
-
- when.tm_hour = 0;
- when.tm_min = 0;
- when.tm_sec = 0;
-
- if (when.tm_year == -1)
- when.tm_year = ((year == -1) ? date_t::current_year : year) - 1900;
-
- if (when.tm_mon == -1)
- when.tm_mon = 0;
-
- if (when.tm_mday == -1)
- when.tm_mday = 1;
-
- *result = std::mktime(&when);
-
- return true;
- }
-
- bool quick_parse_date(const char * date_str, std::time_t * result)
- {
- return parse_date(date_str, result, date_t::current_year);
- }
-}
diff --git a/datetime.h b/datetime.h
deleted file mode 100644
index 377f7f00..00000000
--- a/datetime.h
+++ /dev/null
@@ -1,307 +0,0 @@
-#ifndef _DATETIME_H
-#define _DATETIME_H
-
-#include <ctime>
-#include <sstream>
-
-#include "error.h"
-
-class date_error : public error {
- public:
- date_error(const std::string& reason) throw() : error(reason) {}
- virtual ~date_error() throw() {}
-};
-
-struct interval_t;
-class datetime_t;
-
-class date_t
-{
- public:
- static date_t now;
- static const char * formats[];
- static int current_year;
- static std::string input_format;
- static std::string output_format;
-
- std::time_t when;
-
- date_t() : when(0) {}
- date_t(const date_t& _when) : when(_when.when) {}
- date_t(const datetime_t& _when);
- date_t(const std::time_t _when) : when(_when) {
-#if 0
- struct std::tm * moment = std::localtime(&_when);
- moment->tm_hour = 0;
- moment->tm_min = 0;
- moment->tm_sec = 0;
- when = std::mktime(moment);
-#endif
- }
- date_t(const interval_t& period);
- date_t(const std::string& _when);
-
- virtual ~date_t() {}
-
- date_t& operator=(const date_t& _when) {
- when = _when.when;
- return *this;
- }
- date_t& operator=(const std::time_t _when) {
- return *this = date_t(_when);
- }
- date_t& operator=(const datetime_t& _when) {
- return *this = date_t(_when);
- }
- date_t& operator=(const interval_t& period) {
- return *this = date_t(period);
- }
- date_t& operator=(const std::string& _when) {
- return *this = date_t(_when);
- }
-
- date_t& operator+=(const interval_t& period);
-
- long operator-=(const date_t& date) {
- return (when - date.when) / 86400;
- }
-
- virtual date_t& operator+=(const long days) {
- // jww (2006-03-26): This is not accurate enough when DST is in effect!
- assert(0);
- when += days * 86400;
- return *this;
- }
- virtual date_t& operator-=(const long days) {
- assert(0);
- when -= days * 86400;
- return *this;
- }
-
-#define DEF_DATE_OP(OP) \
- bool operator OP(const date_t& other) const { \
- return when OP other.when; \
- }
-
- DEF_DATE_OP(<)
- DEF_DATE_OP(<=)
- DEF_DATE_OP(>)
- DEF_DATE_OP(>=)
- DEF_DATE_OP(==)
- DEF_DATE_OP(!=)
-
- operator bool() const {
- return when != 0;
- }
- operator std::string() const {
- return to_string();
- }
-
- std::string to_string(const std::string& format = output_format) const {
- char buf[64];
- std::strftime(buf, 63, format.c_str(), localtime());
- return buf;
- }
-
- int year() const {
- return localtime()->tm_year + 1900;
- }
- int month() const {
- return localtime()->tm_mon + 1;
- }
- int day() const {
- return localtime()->tm_mday;
- }
- int wday() const {
- return localtime()->tm_wday;
- }
-
- std::tm * localtime() const {
- return std::localtime(&when);
- }
-
- void write(std::ostream& out,
- const std::string& format = output_format) const {
- out << to_string(format);
- }
-
- friend class datetime_t;
- friend struct interval_t;
-};
-
-inline long operator-(const date_t& left, const date_t& right) {
- date_t temp(left);
- temp -= right;
- return (long)temp;
-}
-
-inline date_t operator+(const date_t& left, const long days) {
- date_t temp(left);
- temp += days;
- return temp;
-}
-
-inline date_t operator-(const date_t& left, const long days) {
- date_t temp(left);
- temp -= days;
- return temp;
-}
-
-inline std::ostream& operator<<(std::ostream& out, const date_t& moment) {
- moment.write(out);
- return out;
-}
-
-class datetime_error : public error {
- public:
- datetime_error(const std::string& reason) throw() : error(reason) {}
- virtual ~datetime_error() throw() {}
-};
-
-class datetime_t : public date_t
-{
- public:
- static datetime_t now;
-
- datetime_t() : date_t() {}
- datetime_t(const datetime_t& _when) : date_t(_when.when) {}
- datetime_t(const date_t& _when) : date_t(_when) {}
-
- datetime_t(const std::time_t _when) : date_t(_when) {}
- datetime_t(const std::string& _when);
-
- datetime_t& operator=(const datetime_t& _when) {
- when = _when.when;
- return *this;
- }
- datetime_t& operator=(const date_t& _when) {
- when = _when.when;
- return *this;
- }
- datetime_t& operator=(const std::time_t _when) {
- return *this = datetime_t(_when);
- }
- datetime_t& operator=(const std::string& _when) {
- return *this = datetime_t(_when);
- }
-
- long operator-=(const datetime_t& date) {
- return when - date.when;
- }
-
- virtual datetime_t& operator+=(const long secs) {
- when += secs;
- return *this;
- }
- virtual datetime_t& operator-=(const long secs) {
- when -= secs;
- return *this;
- }
-
-#define DEF_DATETIME_OP(OP) \
- bool operator OP(const datetime_t& other) const { \
- return when OP other.when; \
- }
-
- DEF_DATETIME_OP(<)
- DEF_DATETIME_OP(<=)
- DEF_DATETIME_OP(>)
- DEF_DATETIME_OP(>=)
- DEF_DATETIME_OP(==)
- DEF_DATETIME_OP(!=)
-
- int hour() const {
- return localtime()->tm_hour;
- }
- int min() const {
- return localtime()->tm_min;
- }
- int sec() const {
- return localtime()->tm_sec;
- }
-
- friend inline long operator-(const datetime_t& left, const datetime_t& right) {
- std::time_t left_time = left.when;
- std::time_t right_time = right.when;
- return long(left_time) - long(right_time);
- }
-};
-
-inline datetime_t operator+(const datetime_t& left, const long seconds) {
- datetime_t temp(left);
- temp += seconds;
- return temp;
-}
-
-inline datetime_t operator-(const datetime_t& left, const long seconds) {
- datetime_t temp(left);
- temp -= seconds;
- return temp;
-}
-
-inline std::ostream& operator<<(std::ostream& out,
- const datetime_t& moment) {
- char buf[64];
- std::strftime(buf, 63, (date_t::output_format + " %H:%M:%S").c_str(),
- moment.localtime());
- out << buf;
- return out;
-}
-
-struct interval_t
-{
- int years;
- int months;
- int days;
- int hours;
- int minutes;
- int seconds;
-
- datetime_t begin;
- datetime_t end;
-
- interval_t(int _days = 0, int _months = 0, int _years = 0,
- const date_t& _begin = date_t(),
- const date_t& _end = date_t())
- : years(_years), months(_months), days(_days),
- hours(0), minutes(0), seconds(0),
- begin(_begin), end(_end) {}
-
- interval_t(const std::string& desc)
- : years(0), months(0), days(0),
- hours(0), minutes(0), seconds(0) {
- std::istringstream stream(desc);
- parse(stream);
- }
-
- operator bool() const {
- return (years > 0 || months > 0 || days > 0 ||
- hours > 0 || minutes > 0 || seconds > 0);
- }
-
- void start(const datetime_t& moment) {
- begin = first(moment);
- }
- datetime_t first(const datetime_t& moment = datetime_t()) const;
- datetime_t increment(const datetime_t&) const;
-
- void parse(std::istream& in);
-};
-
-inline date_t::date_t(const interval_t& period) {
- when = period.first().when;
-}
-
-inline date_t& date_t::operator+=(const interval_t& period) {
- return *this = period.increment(*this);
-}
-
-inline date_t::date_t(const datetime_t& _when) {
- struct std::tm * moment = _when.localtime();
- moment->tm_hour = 0;
- moment->tm_min = 0;
- moment->tm_sec = 0;
- when = std::mktime(moment);
-}
-
-#endif // _DATETIME_H
diff --git a/debug.cc b/debug.cc
deleted file mode 100644
index b3b140bc..00000000
--- a/debug.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-#include "debug.h"
-
-#ifdef DEBUG_ENABLED
-
-#include <map>
-#include <fstream>
-
-#include <unistd.h> // for the `write' method
-
-int offset = 0;
-
-std::map<void *, int> ptrs;
-
-#define PRINT_INC(x) { \
- char buf[128]; \
- std::sprintf(buf, "%d: %p: %s", ++offset, ptr, x); \
- write(1, buf, std::strlen(buf)); \
-}
-
-#define PRINT_DEC(x) { \
- char buf[128]; \
- std::sprintf(buf, "%d: %p: %s", --offset, ptr, x); \
- write(1, buf, std::strlen(buf)); \
-}
-
-void * operator new(std::size_t size) throw (std::bad_alloc) {
- void * ptr = std::malloc(size);
- if (DEBUG("debug.alloc")) {
- PRINT_INC("void * operator new(std::size_t size) throw (std::bad_alloc)\n");
- }
- return ptr;
-}
-void * operator new[](std::size_t size) throw (std::bad_alloc) {
- void * ptr = std::malloc(size);
- if (DEBUG("debug.alloc")) {
- PRINT_INC("void * operator new[](std::size_t) throw (std::bad_alloc)\n");
- }
- return ptr;
-}
-void * operator new(std::size_t size, const std::nothrow_t&) throw() {
- void * ptr = std::malloc(size);
- if (DEBUG("debug.alloc")) {
- PRINT_INC("void * operator new(std::size_t size, const std::nothrow_t&) throw()\n");
- }
- return ptr;
-}
-void * operator new[](std::size_t size, const std::nothrow_t&) throw() {
- void * ptr = std::malloc(size);
- if (DEBUG("debug.alloc")) {
- PRINT_INC("void * operator new[](std::size_t size, const std::nothrow_t&) throw()\n");
- }
- return ptr;
-}
-void operator delete(void * ptr) throw() {
- if (DEBUG("debug.alloc")) {
- PRINT_DEC("void operator delete(void * ptr) throw()\n");
- }
- std::free(ptr);
-}
-void operator delete[](void * ptr) throw() {
- if (DEBUG("debug.alloc")) {
- PRINT_DEC("void operator delete[](void * ptr) throw()\n");
- }
- std::free(ptr);
-}
-void operator delete(void * ptr, const std::nothrow_t&) throw() {
- if (DEBUG("debug.alloc")) {
- PRINT_DEC("void operator delete(void * ptr, const std::nothrow_t&) throw()\n");
- }
- std::free(ptr);
-}
-void operator delete[](void * ptr, const std::nothrow_t&) throw() {
- if (DEBUG("debug.alloc")) {
- PRINT_DEC("void operator delete[](void * ptr, const std::nothrow_t&) throw()\n");
- }
- std::free(ptr);
-}
-
-std::ostream * _debug_stream = &std::cerr;
-bool _free_debug_stream = false;
-
-bool _debug_active(const char * const cls) {
- if (char * debug = std::getenv("DEBUG_CLASS")) {
- static const char * error;
- static int erroffset;
- static int ovec[30];
- static pcre * class_regexp = pcre_compile(debug, PCRE_CASELESS,
- &error, &erroffset, NULL);
- return pcre_exec(class_regexp, NULL, cls, std::strlen(cls),
- 0, 0, ovec, 30) >= 0;
- }
- return false;
-}
-
-static struct init_streams {
- init_streams() {
- // If debugging is enabled and DEBUG_FILE is set, all debugging
- // output goes to that file.
- if (const char * p = std::getenv("DEBUG_FILE")) {
- _debug_stream = new std::ofstream(p);
- _free_debug_stream = true;
- }
- }
- ~init_streams() {
- if (_free_debug_stream && _debug_stream) {
- delete _debug_stream;
- _debug_stream = NULL;
- }
- }
-} _debug_init;
-
-#endif // DEBUG_ENABLED
-
-#if DEBUG_LEVEL >= BETA
-
-#include <string>
-
-void debug_assert(const std::string& reason,
- const std::string& file,
- unsigned long line)
-{
- throw new fatal_assert(reason, new file_context(file, line));
-}
-
-#endif
diff --git a/debug.h b/debug.h
deleted file mode 100644
index 81083ad3..00000000
--- a/debug.h
+++ /dev/null
@@ -1,146 +0,0 @@
-#ifndef _DEBUG_H
-#define _DEBUG_H
-
-#define DEVELOPER 4
-#define ALPHA 3
-#define BETA 2
-#define RELEASE 1
-#define NO_SEATBELT 0
-
-#ifndef DEBUG_LEVEL
-#define DEBUG_LEVEL NO_SEATBELT
-#endif
-
-#if DEBUG_LEVEL >= RELEASE
-#include "error.h"
-
-#ifdef assert
-#undef assert
-#endif
-#if DEBUG_LEVEL >= BETA
-void debug_assert(const std::string& reason,
- const std::string& file,
- unsigned long line);
-#define assert(x) \
- if (! (x)) \
- debug_assert(#x, __FILE__, __LINE__)
-#else
-#define assert(x) \
- if (! (x)) \
- throw new fatal_assert(#x, new file_context(__FILE__, __LINE__))
-#endif
-#else
-#ifdef assert
-#undef assert
-#endif
-#define assert(x)
-#endif
-
-//////////////////////////////////////////////////////////////////////
-//
-// General debugging facilities
-//
-// - In developer level, all checking and debugging facilities are
-// active.
-//
-// - Alpha level does not include performance degrading
-// VALIDATE calls.
-//
-// - Beta level is like Alpha, but does not include debugging
-// facilities.
-//
-// - Release level does not include CONFIRM checks, but does include
-// assert calls.
-//
-// - Running with no seatbelt disables all checking except for normal
-// syntax and semantic error checking.
-
-#if DEBUG_LEVEL >= ALPHA
-
-#include <pcre.h>
-#include <cstring>
-#include <new>
-#include <iostream>
-#include <cstdlib>
-
-#include "datetime.h"
-
-#define DEBUG_ENABLED
-
-extern std::ostream * _debug_stream;
-extern bool _free_debug_stream;
-
-bool _debug_active(const char * const cls);
-
-#define DEBUG_CLASS(cls) static const char * const _debug_cls = (cls)
-
-#define DEBUG(cls) (_debug_active(cls))
-#define DEBUG_() DEBUG(_debug_cls)
-
-#define DEBUG_IF(cls) if (_debug_active(cls))
-#define DEBUG_IF_() if (_debug_active(_debug_cls))
-
-#define DEBUG_PRINT(cls, x) \
- if (_debug_stream && _debug_active(cls)) { \
- *_debug_stream << x << std::endl; \
- }
-#define DEBUG_PRINT_(x) DEBUG_PRINT(_debug_cls, x)
-
-#define DEBUG_PRINT_TIME(cls, x) { \
- DEBUG_PRINT(cls, #x << " is " << x); \
-}
-
-#define DEBUG_PRINT_TIME_(x) DEBUG_PRINT_TIME(_debug_cls, x)
-
-#define CONFIRM(x) assert(x)
-
-#if DEBUG_LEVEL == DEVELOPER
-#define VALIDATE(x) assert(x)
-#else
-#define VALIDATE(x)
-#endif
-
-void * operator new(std::size_t) throw (std::bad_alloc);
-void * operator new[](std::size_t) throw (std::bad_alloc);
-void operator delete(void*) throw();
-void operator delete[](void*) throw();
-void * operator new(std::size_t, const std::nothrow_t&) throw();
-void * operator new[](std::size_t, const std::nothrow_t&) throw();
-void operator delete(void*, const std::nothrow_t&) throw();
-void operator delete[](void*, const std::nothrow_t&) throw();
-
-#else // DEBUG_LEVEL
-
-#define DEBUG_CLASS(cls)
-#define DEBUG(cls) 0
-#define DEBUG_() 0
-#define DEBUG_IF(cls)
-#define DEBUG_IF_()
-#define DEBUG_PRINT(cls, x)
-#define DEBUG_PRINT_(x)
-#define DEBUG_PRINT_TIME(cls, x)
-#define DEBUG_PRINT_TIME_(x)
-
-#define VALIDATE(x)
-
-#if DEBUG_LEVEL == NO_SEATBELT
-
-#ifdef assert
-#undef assert
-#endif
-#define assert(x)
-#define CONFIRM(x)
-
-#elif DEBUG_LEVEL >= RELEASE
-
-#define CONFIRM(x)
-
-#elif DEBUG_LEVEL >= BETA
-
-#define CONFIRM(x) assert(x)
-
-#endif
-
-#endif // DEBUG_LEVEL
-
-#endif // _DEBUG_H
diff --git a/derive.cc b/derive.cc
deleted file mode 100644
index 1b74578f..00000000
--- a/derive.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-#include "derive.h"
-#include "datetime.h"
-#include "error.h"
-#include "mask.h"
-#include "walk.h"
-
-#include <memory>
-
-namespace ledger {
-
-entry_t * derive_new_entry(journal_t& journal,
- strings_list::iterator i,
- strings_list::iterator end)
-{
- std::auto_ptr<entry_t> added(new entry_t);
-
- entry_t * matching = NULL;
-
- added->_date = *i++;
- if (i == end)
- throw new error("Too few arguments to 'entry'");
-
- mask_t regexp(*i++);
-
- entries_list::reverse_iterator j;
- for (j = journal.entries.rbegin();
- j != journal.entries.rend();
- j++)
- if (regexp.match((*j)->payee)) {
- matching = *j;
- break;
- }
-
- added->payee = matching ? matching->payee : regexp.pattern;
-
- if (! matching) {
- account_t * acct;
- if (i == end || ((*i)[0] == '-' || std::isdigit((*i)[0]))) {
- acct = journal.find_account("Expenses");
- }
- else if (i != end) {
- acct = journal.find_account_re(*i);
- if (! acct)
- acct = journal.find_account(*i);
- assert(acct);
- i++;
- }
-
- if (i == end) {
- added->add_transaction(new transaction_t(acct));
- } else {
- transaction_t * xact = new transaction_t(acct, amount_t(*i++));
- added->add_transaction(xact);
-
- if (! xact->amount.commodity()) {
- // If the amount has no commodity, we can determine it given
- // the account by creating a final for the account and then
- // checking if it contains only a single commodity. An
- // account to which only dollars are applied would imply that
- // dollars are wanted now too.
-
- std::auto_ptr<item_handler<transaction_t> > formatter;
- formatter.reset(new set_account_value);
- walk_entries(journal.entries, *formatter.get());
- formatter->flush();
-
- sum_accounts(*journal.master);
-
- value_t total = account_xdata(*acct).total;
- if (total.type == value_t::AMOUNT)
- xact->amount.set_commodity(((amount_t *) total.data)->commodity());
- }
- }
-
- acct = NULL;
-
- if (i != end) {
- if (! acct)
- acct = journal.find_account_re(*i);
- if (! acct)
- acct = journal.find_account(*i);
- }
-
- if (! acct) {
- if (journal.basket)
- acct = journal.basket;
- else
- acct = journal.find_account("Equity");
- }
-
- added->add_transaction(new transaction_t(acct));
- }
- else if (i == end) {
- // If no argument were given but the payee, assume the user wants
- // to see the same transaction as last time.
- added->code = matching->code;
-
- for (transactions_list::iterator k = matching->transactions.begin();
- k != matching->transactions.end();
- k++)
- added->add_transaction(new transaction_t(**k));
- }
- else if ((*i)[0] == '-' || std::isdigit((*i)[0])) {
- transaction_t * m_xact, * xact, * first;
- m_xact = matching->transactions.front();
-
- first = xact = new transaction_t(m_xact->account, amount_t(*i++));
- added->add_transaction(xact);
-
- if (! xact->amount.commodity())
- xact->amount.set_commodity(m_xact->amount.commodity());
-
- m_xact = matching->transactions.back();
-
- xact = new transaction_t(m_xact->account, - first->amount);
- added->add_transaction(xact);
-
- if (i != end) {
- account_t * acct = journal.find_account_re(*i);
- if (! acct)
- acct = journal.find_account(*i);
- assert(acct);
- added->transactions.back()->account = acct;
- }
- }
- else {
- account_t * draw_acct = NULL;
-
- while (i != end) {
- std::string& re_pat(*i++);
- account_t * acct = NULL;
- amount_t * amt = NULL;
-
- mask_t acct_regex(re_pat);
-
- for (; j != journal.entries.rend(); j++)
- if (regexp.match((*j)->payee)) {
- entry_t * entry = *j;
- for (transactions_list::const_iterator x =
- entry->transactions.begin();
- x != entry->transactions.end();
- x++)
- if (acct_regex.match((*x)->account->fullname())) {
- acct = (*x)->account;
- amt = &(*x)->amount;
- matching = entry;
- goto found;
- }
- }
-
- found:
- transaction_t * xact;
- if (i == end) {
- if (amt)
- xact = new transaction_t(acct, *amt);
- else
- xact = new transaction_t(acct);
- } else {
- amount_t amount(*i++);
-
- strings_list::iterator x = i;
- if (i != end && ++x == end) {
- draw_acct = journal.find_account_re(*i);
- if (! draw_acct)
- draw_acct = journal.find_account(*i);
- i++;
- }
-
- if (! acct)
- acct = journal.find_account_re(re_pat);
- if (! acct)
- acct = journal.find_account(re_pat);
-
- xact = new transaction_t(acct, amount);
- if (! xact->amount.commodity()) {
- if (amt)
- xact->amount.set_commodity(amt->commodity());
- else if (commodity_t::default_commodity)
- xact->amount.set_commodity(*commodity_t::default_commodity);
- }
- }
- added->add_transaction(xact);
- }
-
- if (! draw_acct) {
- assert(matching->transactions.back()->account);
- draw_acct = matching->transactions.back()->account;
- }
- if (draw_acct)
- added->add_transaction(new transaction_t(draw_acct));
- }
-
- done:
- if (! run_hooks(journal.entry_finalize_hooks, *added, false) ||
- ! added->finalize() ||
- ! run_hooks(journal.entry_finalize_hooks, *added, true))
- throw new error("Failed to finalize derived entry (check commodities)");
-
- return added.release();
-}
-
-} // namespace ledger
diff --git a/derive.h b/derive.h
deleted file mode 100644
index 0df7f231..00000000
--- a/derive.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _DERIVE_H
-#define _DERIVE_H
-
-#include "journal.h"
-
-namespace ledger {
-
-entry_t * derive_new_entry(journal_t& journal,
- strings_list::iterator begin,
- strings_list::iterator end);
-
-} // namespace ledger
-
-#endif // _DERIVE_H
diff --git a/dist/Portfile b/dist/Portfile
new file mode 100644
index 00000000..c7305e96
--- /dev/null
+++ b/dist/Portfile
@@ -0,0 +1,77 @@
+# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
+# $Id$
+
+PortSystem 1.0
+
+name ledger
+version 3.0
+homepage http://www.newartisans.com/software/ledger.html
+categories finance accounting reporting
+
+description A command-line, double-entry accounting tool.
+long_description Ledger is a powerful, double-entry accounting system that \
+ is accessed from the UNIX command-line.
+
+maintainers johnw@newartisans.com
+
+platforms darwin
+
+use_bzip2 no
+master_sites ftp://ftp.newartisans.com/pub/ledger/:source
+distname ${name}-${version}
+distfiles ${distname}${extract.suffix}:source
+checksums ${distname}${extract.suffix} \
+ md5 7d2ebb3fbc0ca14e34f4aada9fe764a0 \
+ sha1 d00ca4d61f28793c22be892411491d5ff48f156b \
+ rmd160 e6ef6e0acfa125a88927ac399ec8e37fbbe1fe66
+
+depends_build port:automake \
+ port:autoconf \
+ port:libtool
+
+depends_lib port:gmp \
+ port:mpfr \
+ port:boost
+
+configure.args --with-extra-includes=${prefix}/include \
+ --with-extra-libs=${prefix}/lib
+
+#patchfiles patch-admin-libtool.m4.in.diff \
+# patch-ledger-ProjectFile.cpp.diff
+
+build.args DYLD_LIBRARY_PATH=${worksrcpath}/ledger/.libs
+
+platform darwin 9 {}
+
+destroot.args DESTDIR=${destroot}${prefix} \
+ DYLD_LIBRARY_PATH=${worksrcpath}/ledger/.libs \
+ docprefix=${destroot}/share/doc
+
+post-destroot {}
+
+variant ofx description {Allow reading of OFX data files} {
+ depends_lib-append port:libofx
+}
+
+variant debug description {Enable debug mode} {
+ configure.args-append --enable-debug=yes
+}
+
+variant python25 description {build python 2.5 support} conflicts python26 {
+ set pyversion 2.5
+ depends_lib-delete port:boost
+ depends_lib-append port:boost+python25 \
+ port:python[strsed ${pyversion} {g/[.]//}]
+}
+
+variant python26 description {build python 2.6 support} conflicts python25 {
+ set pyversion 2.6
+ depends_lib-delete port:boost
+ depends_lib-append port:boost+python26 \
+ port:python[strsed ${pyversion} {g/[.]//}]
+}
+
+#livecheck.check regex
+#livecheck.url ${homepage}
+#livecheck.regex "Latest Stable Ledger \\(Version (\\d+.\\d+.\\d+)\\)"
+
diff --git a/dist/pkg/ledger.pmdoc/01libgmp-contents.xml b/dist/pkg/ledger.pmdoc/01libgmp-contents.xml
new file mode 100644
index 00000000..0a430288
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/01libgmp-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="libgmp.3.4.2.dylib" o="root" g="admin" p="33261" pt="/opt/local/lib/libgmp.3.4.2.dylib" m="false" t="file"/></pkg-contents> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/01libgmp.xml b/dist/pkg/ledger.pmdoc/01libgmp.xml
new file mode 100644
index 00000000..23719cb0
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/01libgmp.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="20CB3809-D9CA-4DC8-9D1C-7AF1A63BB48A"><config><identifier>com.newartisans.ledger261.libgmp342.pkg</identifier><version>1</version><description/><post-install type="none"/><requireAuthorization/><installFrom>/opt/local/lib/libgmp.3.4.2.dylib</installFrom><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>parent</mod><mod>installTo.path</mod><mod>installTo</mod></config><contents><file-list>01libgmp-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/02libintl-contents.xml b/dist/pkg/ledger.pmdoc/02libintl-contents.xml
new file mode 100644
index 00000000..c48f3143
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/02libintl-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="libintl.8.0.2.dylib" o="root" g="admin" p="33188" pt="/opt/local/lib/libintl.8.0.2.dylib" m="false" t="file"/></pkg-contents> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/02libintl.xml b/dist/pkg/ledger.pmdoc/02libintl.xml
new file mode 100644
index 00000000..07805206
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/02libintl.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="45E37CF4-128B-4810-9BC8-BDE24D0C2D31"><config><identifier>com.newartisans.ledger261.libintl802.pkg</identifier><version>1</version><description/><post-install type="none"/><requireAuthorization/><installFrom>/opt/local/lib/libintl.8.0.2.dylib</installFrom><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>parent</mod><mod>installTo.path</mod><mod>installTo</mod></config><contents><file-list>02libintl-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/03libosp-contents.xml b/dist/pkg/ledger.pmdoc/03libosp-contents.xml
new file mode 100644
index 00000000..f620ae64
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/03libosp-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="libosp.5.0.0.dylib" o="root" g="admin" p="33261" pt="/opt/local/lib/libosp.5.0.0.dylib" m="false" t="file"/></pkg-contents> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/03libosp.xml b/dist/pkg/ledger.pmdoc/03libosp.xml
new file mode 100644
index 00000000..0c355399
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/03libosp.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="68EFD971-45E8-41F0-A238-48A0D7DB919A"><config><identifier>com.newartisans.ledger261.libosp500.pkg</identifier><version>1</version><description/><post-install type="none"/><requireAuthorization/><installFrom>/opt/local/lib/libosp.5.0.0.dylib</installFrom><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>parent</mod><mod>installTo.path</mod><mod>installTo</mod></config><contents><file-list>03libosp-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/04libofx-contents.xml b/dist/pkg/ledger.pmdoc/04libofx-contents.xml
new file mode 100644
index 00000000..9fd6b67f
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/04libofx-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="libofx.3.0.1.dylib" o="root" g="admin" p="33261" pt="/opt/local/lib/libofx.3.0.1.dylib" m="false" t="file"/></pkg-contents> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/04libofx.xml b/dist/pkg/ledger.pmdoc/04libofx.xml
new file mode 100644
index 00000000..44ac60c7
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/04libofx.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="25459941-C854-492F-BBCB-AB386E085408"><config><identifier>com.newartisans.ledger261.libofx301.pkg</identifier><version>1</version><description/><post-install type="none"/><requireAuthorization/><installFrom>/opt/local/lib/libofx.3.0.1.dylib</installFrom><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>parent</mod><mod>installTo.path</mod><mod>installTo</mod></config><contents><file-list>04libofx-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/05libpcre-contents.xml b/dist/pkg/ledger.pmdoc/05libpcre-contents.xml
new file mode 100644
index 00000000..244c7d22
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/05libpcre-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="libpcre.0.0.1.dylib" o="root" g="admin" p="33261" pt="/opt/local/lib/libpcre.0.0.1.dylib" m="false" t="file"/></pkg-contents> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/05libpcre.xml b/dist/pkg/ledger.pmdoc/05libpcre.xml
new file mode 100644
index 00000000..28d7188b
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/05libpcre.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="C507CC8C-58DE-41FF-ACAF-393176088653"><config><identifier>com.newartisans.ledger261.libpcre001.pkg</identifier><version>1</version><description/><post-install type="none"/><requireAuthorization/><installFrom>/opt/local/lib/libpcre.0.0.1.dylib</installFrom><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>parent</mod><mod>installTo.path</mod><mod>installTo</mod></config><contents><file-list>05libpcre-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/06ledger-contents.xml b/dist/pkg/ledger.pmdoc/06ledger-contents.xml
new file mode 100644
index 00000000..277b9294
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/06ledger-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="ledger.pdf" o="johnw" g="501" p="33188" pt="/Users/johnw/Products/2.6.1/ledger.pdf" m="false" t="file"/></pkg-contents> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/06ledger.xml b/dist/pkg/ledger.pmdoc/06ledger.xml
new file mode 100644
index 00000000..d90d9a33
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/06ledger.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="332F048F-7778-42FF-AABB-A519AC0CCEC5"><config><identifier>com.newartisans.ledger261.ledger.pkg</identifier><version>1</version><description/><post-install type="none"/><requireAuthorization/><installFrom>/Users/johnw/Products/2.6.1/ledger.pdf</installFrom><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>parent</mod></config><contents><file-list>06ledger-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/07ledger-contents.xml b/dist/pkg/ledger.pmdoc/07ledger-contents.xml
new file mode 100644
index 00000000..8314ef4d
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/07ledger-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="ledger.info" o="johnw" g="501" p="33188" pt="/Users/johnw/Projects/branches/2.6.1/ledger.info" m="false" t="file"/></pkg-contents> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/07ledger.xml b/dist/pkg/ledger.pmdoc/07ledger.xml
new file mode 100644
index 00000000..582ed128
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/07ledger.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="AF6A8ADD-2251-4548-B762-B0FFC7D664DE"><config><identifier>com.newartisans.ledger261.ledger-1.pkg</identifier><version>1</version><description/><post-install type="none"/><requireAuthorization/><installFrom>/Users/johnw/Projects/branches/2.6.1/ledger.info</installFrom><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>parent</mod><mod>scripts.postinstall.path</mod><mod>installTo.path</mod><mod>installTo</mod></config><contents><file-list>07ledger-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/08ledger-contents.xml b/dist/pkg/ledger.pmdoc/08ledger-contents.xml
new file mode 100644
index 00000000..6adf8d2c
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/08ledger-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="ledger.el" o="johnw" g="501" p="33188" pt="/Users/johnw/Projects/branches/2.6.1/ledger.el" m="false" t="file"/></pkg-contents> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/08ledger.xml b/dist/pkg/ledger.pmdoc/08ledger.xml
new file mode 100644
index 00000000..28489728
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/08ledger.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="3E76E43D-8A47-4CE2-B9C9-7F8BD8040222"><config><identifier>com.newartisans.ledger261.ledger-2.pkg</identifier><version>1</version><description/><post-install type="none"/><requireAuthorization/><installFrom>/Users/johnw/Projects/branches/2.6.1/ledger.el</installFrom><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>parent</mod><mod>installTo.path</mod><mod>installTo</mod></config><contents><file-list>08ledger-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref> \ No newline at end of file
diff --git a/dist/pkg/ledger.pmdoc/index.xml b/dist/pkg/ledger.pmdoc/index.xml
new file mode 100644
index 00000000..0c8c8963
--- /dev/null
+++ b/dist/pkg/ledger.pmdoc/index.xml
@@ -0,0 +1 @@
+<pkmkdoc spec="1.12"><properties><title>Ledger 2.6.1</title><build>/Users/johnw/Projects/ledger/Ledger 2.6.1.pkg</build><organization>com.newartisans</organization><userSees ui="easy"/><min-target os="3"/><domain system="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><description>Ledger is a command-line, double-entry accounting system.</description><contents><choice title="libgmp" id="gmp" description="The GNP multi-precision math library. " starts_selected="true" starts_enabled="true" starts_hidden="false"><customLoc mod="true">/usr/lib</customLoc><pkgref id="com.newartisans.ledger261.libgmp342.pkg"/></choice><choice title="libintl.8.0.2" id="choice9" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.newartisans.ledger261.libintl802.pkg"/></choice><choice title="libosp.5.0.0" id="choice10" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.newartisans.ledger261.libosp500.pkg"/></choice><choice title="libofx.3.0.1" id="choice11" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.newartisans.ledger261.libofx301.pkg"/></choice><choice title="libpcre.0.0.1" id="choice12" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.newartisans.ledger261.libpcre001.pkg"/></choice><choice title="ledger" id="choice13" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.newartisans.ledger261.ledger.pkg"/><pkgref id="com.newartisans.ledger261.ledger-1.pkg"/></choice><choice title="ledger" id="choice14" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.newartisans.ledger261.ledger-2.pkg"/></choice></contents><resources bg-scale="none" bg-align="topleft"><locale lang="en"><resource relative="true" mod="true" type="license">LICENSE</resource><resource relative="true" mod="true" type="readme">README</resource></locale></resources><requirements><requirement id="sosv" operator="ge" value="'10.5.0'"/></requirements><flags/><item type="file">01libgmp.xml</item><item type="file">02libintl.xml</item><item type="file">03libosp.xml</item><item type="file">04libofx.xml</item><item type="file">05libpcre.xml</item><item type="file">06ledger.xml</item><item type="file">07ledger.xml</item><item type="file">08ledger.xml</item><mod>properties.customizeOption</mod><mod>properties.userDomain</mod><mod>properties.title</mod><mod>description</mod><mod>properties.anywhereDomain</mod><mod>properties.systemDomain</mod></pkmkdoc> \ No newline at end of file
diff --git a/dist/pkg/post-install.sh b/dist/pkg/post-install.sh
new file mode 100755
index 00000000..158ca7c2
--- /dev/null
+++ b/dist/pkg/post-install.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+ln -sf /usr/lib/libexpat.1.5.2.dylib /usr/lib/libexpat.1.dylib
+ln -sf /usr/lib/libexpat.1.5.2.dylib /usr/lib/libexpat.dylib
+
+ln -sf /usr/lib/libgmp.3.4.2.dylib /usr/lib/libgmp.3.dylib
+ln -sf /usr/lib/libgmp.3.4.2.dylib /usr/lib/libgmp.dylib
+
diff --git a/doc/Doxyfile b/doc/Doxyfile
new file mode 100644
index 00000000..53e5460d
--- /dev/null
+++ b/doc/Doxyfile
@@ -0,0 +1,1485 @@
+# Doxyfile 1.5.7.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = Ledger
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 3.0
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = %builddir%/doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene,
+# Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH = %srcdir%/src/
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+# jww (2009-01-31): Enable this toward the end
+#WARN_IF_UNDOCUMENTED = YES
+WARN_IF_UNDOCUMENTED = NO
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = src
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#namespace">Qt Help Project / Namespace</a>.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#virtual-folders">Qt Help Project / Virtual Folders</a>.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file .
+
+QHG_LOCATION =
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature. Other possible values
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 11
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = NO
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = NO
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 1000
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/doc/INSTALL b/doc/INSTALL
new file mode 100644
index 00000000..5458714e
--- /dev/null
+++ b/doc/INSTALL
@@ -0,0 +1,234 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006 Free Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/LICENSE b/doc/LICENSE
index f4b7f221..df1a0028 100644
--- a/LICENSE
+++ b/doc/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+Copyright (c) 2003-2009, John Wiegley. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
diff --git a/doc/LICENSE-sha1 b/doc/LICENSE-sha1
new file mode 100644
index 00000000..8d886177
--- /dev/null
+++ b/doc/LICENSE-sha1
@@ -0,0 +1,13 @@
+Copyright (C) 1998
+Paul E. Jones <paulej@arid.us>
+All Rights Reserved.
+
+This software is licensed as "freeware." Permission to distribute
+this software in source and binary forms is hereby granted without
+a fee. THIS SOFTWARE IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+THE AUTHOR SHALL NOT BE HELD LIABLE FOR ANY DAMAGES RESULTING
+FROM THE USE OF THIS SOFTWARE, EITHER DIRECTLY OR INDIRECTLY, INCLUDING,
+BUT NOT LIMITED TO, LOSS OF DATA OR DATA BEING RENDERED INACCURATE.
+
diff --git a/doc/LICENSE-utfcpp b/doc/LICENSE-utfcpp
new file mode 100644
index 00000000..1751a003
--- /dev/null
+++ b/doc/LICENSE-utfcpp
@@ -0,0 +1,23 @@
+Copyright 2006 Nemanja Trifunovic
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/doc/Ledger.scriv/100.rtfd/TXT.rtf b/doc/Ledger.scriv/100.rtfd/TXT.rtf
new file mode 100644
index 00000000..6e63eede
--- /dev/null
+++ b/doc/Ledger.scriv/100.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Reporting monthly expenses} \ No newline at end of file
diff --git a/doc/Ledger.scriv/101.rtfd/TXT.rtf b/doc/Ledger.scriv/101.rtfd/TXT.rtf
new file mode 100644
index 00000000..8903da0a
--- /dev/null
+++ b/doc/Ledger.scriv/101.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Visualizing with Gnuplot} \ No newline at end of file
diff --git a/doc/Ledger.scriv/102.rtfd/TXT.rtf b/doc/Ledger.scriv/102.rtfd/TXT.rtf
new file mode 100644
index 00000000..b802c607
--- /dev/null
+++ b/doc/Ledger.scriv/102.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsubsection Typical plots} \ No newline at end of file
diff --git a/doc/Ledger.scriv/103.rtfd/TXT.rtf b/doc/Ledger.scriv/103.rtfd/TXT.rtf
new file mode 100644
index 00000000..0b08de68
--- /dev/null
+++ b/doc/Ledger.scriv/103.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Budgeting and forecasting} \ No newline at end of file
diff --git a/doc/Ledger.scriv/104.rtfd/TXT.rtf b/doc/Ledger.scriv/104.rtfd/TXT.rtf
new file mode 100644
index 00000000..5a3b5317
--- /dev/null
+++ b/doc/Ledger.scriv/104.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Budgeting} \ No newline at end of file
diff --git a/doc/Ledger.scriv/105.rtfd/TXT.rtf b/doc/Ledger.scriv/105.rtfd/TXT.rtf
new file mode 100644
index 00000000..ac8750a6
--- /dev/null
+++ b/doc/Ledger.scriv/105.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Forecasting} \ No newline at end of file
diff --git a/doc/Ledger.scriv/106.rtfd/TXT.rtf b/doc/Ledger.scriv/106.rtfd/TXT.rtf
new file mode 100644
index 00000000..5ff5b92d
--- /dev/null
+++ b/doc/Ledger.scriv/106.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Commodities and Currencies} \ No newline at end of file
diff --git a/doc/Ledger.scriv/107.rtfd/TXT.rtf b/doc/Ledger.scriv/107.rtfd/TXT.rtf
new file mode 100644
index 00000000..176c0acc
--- /dev/null
+++ b/doc/Ledger.scriv/107.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Commodity price histories} \ No newline at end of file
diff --git a/doc/Ledger.scriv/108.rtfd/TXT.rtf b/doc/Ledger.scriv/108.rtfd/TXT.rtf
new file mode 100644
index 00000000..135311c3
--- /dev/null
+++ b/doc/Ledger.scriv/108.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Commodity equivalencies} \ No newline at end of file
diff --git a/doc/Ledger.scriv/109.rtfd/TXT.rtf b/doc/Ledger.scriv/109.rtfd/TXT.rtf
new file mode 100644
index 00000000..c6fbe87f
--- /dev/null
+++ b/doc/Ledger.scriv/109.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Accounts and Inventories} \ No newline at end of file
diff --git a/doc/Ledger.scriv/110.rtfd/TXT.rtf b/doc/Ledger.scriv/110.rtfd/TXT.rtf
new file mode 100644
index 00000000..142f6e5a
--- /dev/null
+++ b/doc/Ledger.scriv/110.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Understanding Equity} \ No newline at end of file
diff --git a/doc/Ledger.scriv/111.rtfd/TXT.rtf b/doc/Ledger.scriv/111.rtfd/TXT.rtf
new file mode 100644
index 00000000..0e7f1f4f
--- /dev/null
+++ b/doc/Ledger.scriv/111.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Dealing with Petty Cash} \ No newline at end of file
diff --git a/doc/Ledger.scriv/112.rtfd/TXT.rtf b/doc/Ledger.scriv/112.rtfd/TXT.rtf
new file mode 100644
index 00000000..4aa1111a
--- /dev/null
+++ b/doc/Ledger.scriv/112.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Working with multiple funds and accounts} \ No newline at end of file
diff --git a/doc/Ledger.scriv/113.rtfd/TXT.rtf b/doc/Ledger.scriv/113.rtfd/TXT.rtf
new file mode 100644
index 00000000..1e186706
--- /dev/null
+++ b/doc/Ledger.scriv/113.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Archiving previous years} \ No newline at end of file
diff --git a/doc/Ledger.scriv/114.rtfd/TXT.rtf b/doc/Ledger.scriv/114.rtfd/TXT.rtf
new file mode 100644
index 00000000..750b7c2c
--- /dev/null
+++ b/doc/Ledger.scriv/114.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Virtual postings} \ No newline at end of file
diff --git a/doc/Ledger.scriv/115.rtfd/TXT.rtf b/doc/Ledger.scriv/115.rtfd/TXT.rtf
new file mode 100644
index 00000000..5f612d65
--- /dev/null
+++ b/doc/Ledger.scriv/115.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Automated postings} \ No newline at end of file
diff --git a/doc/Ledger.scriv/116.rtfd/TXT.rtf b/doc/Ledger.scriv/116.rtfd/TXT.rtf
new file mode 100644
index 00000000..cda86226
--- /dev/null
+++ b/doc/Ledger.scriv/116.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Using Emacs to Keep Your Ledger} \ No newline at end of file
diff --git a/doc/Ledger.scriv/117.rtfd/TXT.rtf b/doc/Ledger.scriv/117.rtfd/TXT.rtf
new file mode 100644
index 00000000..72bc5e40
--- /dev/null
+++ b/doc/Ledger.scriv/117.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Using GnuCash to Keep Your Ledger} \ No newline at end of file
diff --git a/doc/Ledger.scriv/118.rtfd/TXT.rtf b/doc/Ledger.scriv/118.rtfd/TXT.rtf
new file mode 100644
index 00000000..b62f7aa3
--- /dev/null
+++ b/doc/Ledger.scriv/118.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Using timeclock to record billable time} \ No newline at end of file
diff --git a/doc/Ledger.scriv/119.rtfd/TXT.rtf b/doc/Ledger.scriv/119.rtfd/TXT.rtf
new file mode 100644
index 00000000..a49da5fc
--- /dev/null
+++ b/doc/Ledger.scriv/119.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Using XML} \ No newline at end of file
diff --git a/doc/Ledger.scriv/12.rtfd/TXT.rtf b/doc/Ledger.scriv/12.rtfd/TXT.rtf
new file mode 100644
index 00000000..8b171ebf
--- /dev/null
+++ b/doc/Ledger.scriv/12.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Building the program} \ No newline at end of file
diff --git a/doc/Ledger.scriv/120.rtfd/TXT.rtf b/doc/Ledger.scriv/120.rtfd/TXT.rtf
new file mode 100644
index 00000000..4170eb76
--- /dev/null
+++ b/doc/Ledger.scriv/120.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Numerics} \ No newline at end of file
diff --git a/doc/Ledger.scriv/121.rtfd/TXT.rtf b/doc/Ledger.scriv/121.rtfd/TXT.rtf
new file mode 100644
index 00000000..0f160c5d
--- /dev/null
+++ b/doc/Ledger.scriv/121.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Basic amounts} \ No newline at end of file
diff --git a/doc/Ledger.scriv/122.rtfd/TXT.rtf b/doc/Ledger.scriv/122.rtfd/TXT.rtf
new file mode 100644
index 00000000..3ad5c7d4
--- /dev/null
+++ b/doc/Ledger.scriv/122.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Journal Representation} \ No newline at end of file
diff --git a/doc/Ledger.scriv/123.rtfd/TXT.rtf b/doc/Ledger.scriv/123.rtfd/TXT.rtf
new file mode 100644
index 00000000..32cf3a44
--- /dev/null
+++ b/doc/Ledger.scriv/123.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Reporting} \ No newline at end of file
diff --git a/doc/Ledger.scriv/124.rtfd/TXT.rtf b/doc/Ledger.scriv/124.rtfd/TXT.rtf
new file mode 100644
index 00000000..6a1f4ffb
--- /dev/null
+++ b/doc/Ledger.scriv/124.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Terminal Interface} \ No newline at end of file
diff --git a/doc/Ledger.scriv/125.rtfd/TXT.rtf b/doc/Ledger.scriv/125.rtfd/TXT.rtf
new file mode 100644
index 00000000..16ca19f7
--- /dev/null
+++ b/doc/Ledger.scriv/125.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section General Utility} \ No newline at end of file
diff --git a/doc/Ledger.scriv/126.rtfd/TXT.rtf b/doc/Ledger.scriv/126.rtfd/TXT.rtf
new file mode 100644
index 00000000..8f83e21b
--- /dev/null
+++ b/doc/Ledger.scriv/126.rtfd/TXT.rtf
@@ -0,0 +1,39 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 This chapter describes ledger's features and serves as a quick\
+reference. You may wish to survey this to get an overview before diving\
+in to the @ref\{Ledger Tutorial\} and more detailed examples that follow.\
+\
+Ledger has a very simple command-line interface, named---enticing\
+enough---@command\{ledger\}. It supports a few reporting commands, and\
+a large number of options for refining the output from those commands.\
+The basic syntax of any ledger command is:\
+\
+@example\
+ledger [OPTIONS...] COMMAND [ARGS...]\
+@end example\
+\
+Command options must always precede the command word. After the\
+command word there may appear any number of arguments. For most\
+commands, these arguments are regular expressions that cause the\
+output to relate only to postings matching those regular\
+expressions. For the @command\{transaction\} command, the arguments have a\
+special meaning, described below.\
+\
+The regular expressions arguments always match the account name that a\
+posting refers to. To match on the payee of the transaction instead,\
+precede the regular expression with @samp\{--\}. For example, the\
+following balance command reports account totals for rent, food and\
+movies, but only those whose payee matches Freddie:\
+\
+@example\
+ledger bal rent food movies -- freddie\
+@end example\
+\
+There are many, many command options available with the\
+@command\{ledger\} command, and it takes a while to master them.\
+However, none of them are required to use the basic reporting\
+commands.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/128.rtfd/TXT.rtf b/doc/Ledger.scriv/128.rtfd/TXT.rtf
new file mode 100644
index 00000000..802e76ad
--- /dev/null
+++ b/doc/Ledger.scriv/128.rtfd/TXT.rtf
@@ -0,0 +1,11 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The @command\{balance\} command reports the current balance of all\
+accounts. It accepts a list of optional regexps, which confine the\
+balance report to the matching accounts. If an account contains\
+multiple types of commodities, each commodity's total is reported\
+separately.\
+} \ No newline at end of file
diff --git a/doc/Ledger.scriv/129.rtfd/TXT.rtf b/doc/Ledger.scriv/129.rtfd/TXT.rtf
new file mode 100644
index 00000000..aa8efb5c
--- /dev/null
+++ b/doc/Ledger.scriv/129.rtfd/TXT.rtf
@@ -0,0 +1,22 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The @command\{register\} command displays all the postings occurring\
+in a single account, line by line. The account regexp must be\
+specified as the only argument to this command. If any regexps occur\
+after the required account name, the register will contain only those\
+postings that match. Very useful for hunting down a particular\
+posting.\
+\
+The output from @command\{register\} is very close to what a typical\
+checkbook, or single-account ledger, would look like. It also shows a\
+running balance. The final running balance of any register should\
+always be the same as the current balance of that account.\
+\
+If you have Gnuplot installed, you may plot the amount or running\
+total of any register by using the script @file\{report\}, which is\
+included in the Ledger distribution. The only requirement is that you\
+add either @option\{-j\} or @option\{-J\} to your register command, in\
+order to plot either the amount or total column, respectively.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/13.rtfd/TXT.rtf b/doc/Ledger.scriv/13.rtfd/TXT.rtf
new file mode 100644
index 00000000..da773be2
--- /dev/null
+++ b/doc/Ledger.scriv/13.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Getting help} \ No newline at end of file
diff --git a/doc/Ledger.scriv/130.rtfd/TXT.rtf b/doc/Ledger.scriv/130.rtfd/TXT.rtf
new file mode 100644
index 00000000..da1d8354
--- /dev/null
+++ b/doc/Ledger.scriv/130.rtfd/TXT.rtf
@@ -0,0 +1,13 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The @command\{print\} command prints out ledger transactions in a textual\
+format that can be parsed by Ledger. They will be properly formatted,\
+and output in the most economic form possible. The ``print'' command\
+also takes a list of optional regexps, which will cause only those\
+postings which match in some way to be printed.\
+\
+The @command\{print\} command can be a handy way to clean up a ledger\
+file whose formatting has gotten out of hand.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/131.rtfd/TXT.rtf b/doc/Ledger.scriv/131.rtfd/TXT.rtf
new file mode 100644
index 00000000..f882f2d9
--- /dev/null
+++ b/doc/Ledger.scriv/131.rtfd/TXT.rtf
@@ -0,0 +1,17 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The @command\{output\} command is very similar to the @command\{print\}\
+command, except that it attempts to replicate the specified ledger\
+file epostly. The format of the command is:\
+\
+@example\
+ledger -f FILENAME output FILENAME\
+@end example\
+\
+Where @file\{FILENAME\} is the name of the ledger file to output. The\
+reason for specifying this command is that only transactions contained\
+within that file will be output, and not an included transactions (as can\
+happen with the @command\{print\} command).} \ No newline at end of file
diff --git a/doc/Ledger.scriv/132.rtfd/TXT.rtf b/doc/Ledger.scriv/132.rtfd/TXT.rtf
new file mode 100644
index 00000000..e3cafbce
--- /dev/null
+++ b/doc/Ledger.scriv/132.rtfd/TXT.rtf
@@ -0,0 +1,10 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The @command\{xml\} command outputs results similar to what\
+@command\{print\} and @command\{register\} display, but as an XML form.\
+This data can then be read in and processed. Use the\
+@option\{--totals\} option to include the running total with each\
+posting.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/133.rtfd/TXT.rtf b/doc/Ledger.scriv/133.rtfd/TXT.rtf
new file mode 100644
index 00000000..3ca78a49
--- /dev/null
+++ b/doc/Ledger.scriv/133.rtfd/TXT.rtf
@@ -0,0 +1,13 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The @command\{emacs\} command outputs results in a form that can be read\
+directly by Emacs Lisp. The format of the sexp is:\
+\
+@example\
+((BEG-POS CLEARED DATE CODE PAYEE\
+ (ACCOUNT AMOUNT)...) ; list of postings\
+ ...) ; list of transactions\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/134.rtfd/TXT.rtf b/doc/Ledger.scriv/134.rtfd/TXT.rtf
new file mode 100644
index 00000000..0e762e0a
--- /dev/null
+++ b/doc/Ledger.scriv/134.rtfd/TXT.rtf
@@ -0,0 +1,8 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The @command\{equity\} command prints out accounts balances as if they\
+were transactions. This makes it easy to establish the starting balances\
+for an account, such as when @ref\{Archiving previous years\}.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/135.rtfd/TXT.rtf b/doc/Ledger.scriv/135.rtfd/TXT.rtf
new file mode 100644
index 00000000..1c14b7ca
--- /dev/null
+++ b/doc/Ledger.scriv/135.rtfd/TXT.rtf
@@ -0,0 +1,13 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The @command\{prices\} command displays the price history for matching\
+commodities. The @option\{-A\} flag is useful with this report, to\
+display the running average price, or @option\{-D\} to show each price's\
+deviation from that average.\
+\
+There is also a @command\{pricesdb\} command which outputs the same\
+information as @command\{prices\}, but does in a format that can be\
+parsed by Ledger.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/136.rtfd/TXT.rtf b/doc/Ledger.scriv/136.rtfd/TXT.rtf
new file mode 100644
index 00000000..339e90d4
--- /dev/null
+++ b/doc/Ledger.scriv/136.rtfd/TXT.rtf
@@ -0,0 +1,57 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The @command\{xact\} commands simplifies the creation of new transactions.\
+It works on the principle that 80% of all postings are variants of\
+earlier postings. Here's how it works:\
+\
+Say you currently have this posting in your ledger file:\
+\
+@smallexample\
+2004/03/15 * Viva Italiano\
+ Expenses:Food $12.45\
+ Expenses:Tips $2.55\
+ Liabilities:MasterCard $-15.00\
+@end smallexample\
+\
+Now it's @samp\{2004/4/9\}, and you've just eating at @samp\{Viva\
+Italiano\} again. The epost amounts are different, but the overall\
+form is the same. With the @command\{xact\} command you can type:\
+\
+@example\
+ledger xact 2004/4/9 viva food 11 tips 2.50\
+@end example\
+\
+This produces the following output:\
+\
+@smallexample\
+2004/04/09 Viva Italiano\
+ Expenses:Food $11.00\
+ Expenses:Tips $2.50\
+ Liabilities:MasterCard $-13.50\
+@end smallexample\
+\
+It works by finding a past posting matching the regular expression\
+@samp\{viva\}, and assuming that any accounts or amounts specified will\
+be similar to that earlier posting. If Ledger does not succeed in\
+generating a new transaction, an error is printed and the exit code is set\
+to @samp\{1\}.\
+\
+There is a shell script in the distribution's @file\{scripts\} directory\
+called @file\{xact\}, which simplifies the task of adding a new transaction\
+to your ledger. It launches @command\{vi\} to confirm that the transaction\
+looks appropriate.\
+\
+Here are a few more examples of the @command\{xact\} command, assuming\
+the above journal transaction:\
+\
+@example\
+ledger xact 4/9 viva 11.50\
+ledger xact 4/9 viva 11.50 checking # (from `checking')\
+ledger xact 4/9 viva food 11.50 tips 8\
+ledger xact 4/9 viva food 11.50 tips 8 cash\
+ledger xact 4/9 viva food $11.50 tips $8 cash\
+ledger xact 4/9 viva dining "DM 11.50"\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/137.rtfd/TXT.rtf b/doc/Ledger.scriv/137.rtfd/TXT.rtf
new file mode 100644
index 00000000..09facf52
--- /dev/null
+++ b/doc/Ledger.scriv/137.rtfd/TXT.rtf
@@ -0,0 +1,19 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 With all of the reports, command-line options are useful to modify the\
+output generated. These command-line options always occur before the\
+command word. This is done to distinguish options from exclusive\
+regular expressions, which also begin with a dash. The basic form for\
+most commands is:\
+\
+@example\
+ledger [OPTIONS] COMMAND [REGEXPS...] [-- [REGEXPS...]]\
+@end example\
+\
+The @var\{OPTIONS\} and @var\{REGEXPS\} expressions are both optional.\
+You could just use @samp\{ledger balance\}, without any options---which\
+prints a summary of all accounts. But for more specific reporting, or\
+to change the appearance of the output, options are needed.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/138.rtfd/TXT.rtf b/doc/Ledger.scriv/138.rtfd/TXT.rtf
new file mode 100644
index 00000000..6d816a84
--- /dev/null
+++ b/doc/Ledger.scriv/138.rtfd/TXT.rtf
@@ -0,0 +1,53 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 These are the most basic command options. Most likely, the user will\
+want to set them using environment variables (see @ref\{Options\}),\
+instead of using actual command-line options:\
+\
+@option\{--help\} (@option\{-h\}) prints a summary of all the options, and\
+what they are used for. This can be a handy way to remember which\
+options do what. This help screen is also printed if ledger is run\
+without a command.\
+\
+@option\{--version\} (@option\{-v\}) prints the current version of ledger\
+and exits. This is useful for sending bug reports, to let the author\
+know which version of ledger you are using.\
+\
+@option\{--file FILE\} (@option\{-f FILE\}) reads FILE as a ledger file.\
+This command may be used multiple times. FILE may also be a list of\
+file names separated by colons. Typically, the environment variable\
+@env\{LEDGER_FILE\} is set, rather than using this command-line option.\
+\
+@option\{--output FILE\} (@option\{-o FILE\}) redirects output from any\
+command to @var\{FILE\}. By default, all output goes to standard\
+output.\
+\
+@option\{--init-file FILE\} (@option\{-i FILE\}) causes FILE to be read by\
+ledger before any other ledger file. This file may not contain any\
+postings, but it may contain option settings. To specify options\
+in the init file, use the same syntax as the command-line. Here's an\
+example init file:\
+\
+@smallexample\
+--price-db ~/finance/.pricedb\
+\
+; ~/.ledgerrc ends here\
+@end smallexample\
+\
+Option settings on the command-line or in the environment always take\
+precedence over settings in the init file.\
+\
+@option\{--cache FILE\} identifies FILE as the default binary cache\
+file. That is, if the ledger files to be read are specified using the\
+environment variable @env\{LEDGER_FILE\}, then whenever a command is\
+finished a binary copy will be written to the specified cache, to\
+speed up the loading time of subsequent queries. This filename can\
+also be given using the environment variable @env\{LEDGER_CACHE\}, or by\
+putting the option into your init file. The @option\{--no-cache\}\
+option causes Ledger to always ignore the binary cache.\
+\
+@option\{--account NAME\} (@option\{-a NAME\}) specifies the default\
+account which QIF file postings are assumed to relate to.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/139.rtfd/TXT.rtf b/doc/Ledger.scriv/139.rtfd/TXT.rtf
new file mode 100644
index 00000000..248f9ba2
--- /dev/null
+++ b/doc/Ledger.scriv/139.rtfd/TXT.rtf
@@ -0,0 +1,102 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 These options change which postings affect the outcome of a\
+report, in ways other than just using regular expressions:\
+\
+@option\{--current\}(@option\{-c\}) displays only transactions occurring on or\
+before the current date.\
+\
+@option\{--begin DATE\} (@option\{-b DATE\}) constrains the report to\
+transactions on or after @var\{DATE\}. Only transactions after that date will be\
+calculated, which means that the running total in the balance report\
+will always start at zero with the first matching transaction. (Note: This\
+is different from using @option\{--display\} to constrain what is\
+displayed).\
+\
+@option\{--end DATE\} (@option\{-e DATE\}) constrains the report so that\
+transactions on or after @var\{DATE\} are not considered. The ending date\
+is inclusive.\
+\
+@option\{--period STR\} (@option\{-p STR\}) sets the reporting period\
+to @var\{STR\}. This will subtotal all matching transactions within each\
+period separately, making it easy to see weekly, monthly, quarterly,\
+etc., posting totals. A period string can even specify the\
+beginning and end of the report range, using simple terms like ``last\
+june'' or ``next month''. For more using period expressions, see\
+@ref\{Period expressions\}.\
+\
+@option\{--period-sort EXPR\} sorts the postings within each\
+reporting period using the value expression @var\{EXPR\}. This is most\
+often useful when reporting monthly expenses, in order to view the\
+highest expense categories at the top of each month:\
+\
+@example\
+ledger -M --period-sort -At reg ^Expenses\
+@end example\
+\
+@option\{--cleared\} (@option\{-C\}) displays only postings whose transaction\
+has been marked ``cleared'' (by placing an asterix to the right of the\
+date).\
+\
+@option\{--uncleared\} (@option\{-U\}) displays only postings whose\
+transaction has not been marked ``cleared'' (i.e., if there is no asterix to\
+the right of the date).\
+\
+@option\{--real\} (@option\{-R\}) displays only real postings, not\
+virtual. (A virtual posting is indicated by surrounding the\
+account name with parentheses or brackets; see the section on using\
+virtual postings for more information).\
+\
+@option\{--actual\} (@option\{-L\}) displays only actual postings, and\
+not those created due to automated postings.\
+\
+@option\{--related\} (@option\{-r\}) displays postings that are\
+related to whichever postings would otherwise have matched the\
+filtering criteria. In the register report, this shows where money\
+went to, or the account it came from. In the balance report, it shows\
+all the accounts affected by transactions having a related posting.\
+For example, if a file had this transaction:\
+\
+@smallexample\
+2004/03/20 Safeway\
+ Expenses:Food $65.00\
+ Expenses:Cash $20.00\
+ Assets:Checking $-85.00\
+@end smallexample\
+\
+And the register command was:\
+\
+@example\
+ledger -r register food\
+@end example\
+\
+The following would be output, showing the postings related to the\
+posting that matched:\
+\
+@smallexample\
+2004/03/20 Safeway Expenses:Cash $-20.00 $-20.00\
+ Assets:Checking $85.00 $65.00\
+@end smallexample\
+\
+@option\{--budget\} is useful for displaying how close your postings\
+meet your budget. @option\{--add-budget\} also shows unbudgeted\
+postings, while @option\{--unbudgeted\} shows only those.\
+@option\{--forecast\} is a related option that projects your budget into\
+the future, showing how it will affect future balances.\
+@xref\{Budgeting and forecasting\}.\
+\
+@option\{--limit EXPR\} (@option\{-l EXPR\}) limits which postings\
+take part in the calculations of a report.\
+\
+@option\{--amount EXPR\} (@option\{-t EXPR\}) changes the value expression\
+used to calculate the ``value'' column in the @command\{register\}\
+report, the amount used to calculate account totals in the\
+@command\{balance\} report, and the values printed in the\
+@command\{equity\} report. @xref\{Value expressions\}.\
+\
+@option\{--total EXPR\} (@option\{-T EXPR\}) sets the value expression\
+used for the ``totals'' column in the @command\{register\} and\
+@command\{balance\} reports.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/14.rtfd/TXT.rtf b/doc/Ledger.scriv/14.rtfd/TXT.rtf
new file mode 100644
index 00000000..8b8da5e6
--- /dev/null
+++ b/doc/Ledger.scriv/14.rtfd/TXT.rtf
@@ -0,0 +1,16 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Ledger is written in ANSI C++, and should compile on any platform. It\
+depends on the GNU multiprecision integer library (libgmp), and the\
+Perl regular expression library (libpcre). It was developed using GNU\
+make and gcc 3.3, on a PowerBook running OS/X.\
+\
+To build and install once you have these libraries on your system,\
+enter these commands:\
+\
+@example\
+./configure && make install\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/140.rtfd/TXT.rtf b/doc/Ledger.scriv/140.rtfd/TXT.rtf
new file mode 100644
index 00000000..5776b207
--- /dev/null
+++ b/doc/Ledger.scriv/140.rtfd/TXT.rtf
@@ -0,0 +1,127 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 These options affect only the output, but not which postings are\
+used to create it:\
+\
+@option\{--collapse\} (@option\{-n\}) causes transactions in a\
+@command\{register\} report with multiple postings to be collapsed\
+into a single, subtotaled transaction.\
+\
+@option\{--subtotal\} (@option\{-s\}) causes all transactions in a\
+@command\{register\} report to be collapsed into a single, subtotaled\
+transaction.\
+\
+@option\{--by-payee\} (@option\{-P\}) reports subtotals by payee.\
+\
+@option\{--comm-as-payee\} (@option\{-x\}) changes the payee of every\
+posting to be the commodity used in that posting. This can be\
+useful when combined with other options, such as @option\{-s\}.\
+\
+@option\{--empty\} (@option\{-E\}) includes even empty accounts in the\
+@command\{balance\} report.\
+\
+@option\{--weekly\} (@option\{-W\}) reports posting totals by the\
+week. The week begins on whichever day of the week begins the month\
+containing that posting. To set a specific begin date, use a\
+period string, such as @samp\{weekly from DATE\}. @option\{--monthly\}\
+(@option\{-M\}) reports posting totals by month; @option\{--yearly\}\
+(@option\{-Y\}) reports posting totals by year. For more complex\
+period, using the @option\{--period\} option described above.\
+\
+@option\{--dow\} reports postings totals for each day of the week.\
+This is an easy way to see if weekend spending is more than on\
+weekdays.\
+\
+@option\{--sort EXPR\} (@option\{-S EXPR\}) sorts a report by comparing\
+the values determined using the value expression @var\{EXPR\}. For\
+example, using @option\{-S -UT\} in the balance report will sort account\
+balances from greatest to least, using the absolute value of the\
+total. For more on how to use value expressions, see @ref\{Value\
+expressions\}.\
+\
+@option\{--wide\} (@option\{-w\}) causes the default @command\{register\}\
+report to assume 132 columns instead of 80.\
+\
+@option\{--head\} causes only the first N transactions to be printed. This\
+is different from using the command-line utility @command\{head\}, which\
+would limit to the first N postings. @option\{--tail\} outputs only\
+the last N transactions. Both options may be used simultaneously. If a\
+negative amount is given, it will invert the meaning of the flag\
+(instead of the first five transactions being printed, for example, it\
+would print all but the first five).\
+\
+@option\{--pager\} tells Ledger to pass its output to the given pager\
+program---very useful when the output is especially long. This\
+behavior can be made the default by setting the @env\{LEDGER_PAGER\}\
+environment variable.\
+\
+@option\{--average\} (@option\{-A\}) reports the average posting\
+value.\
+\
+@option\{--deviation\} (@option\{-D\}) reports each posting's\
+deviation from the average. It is only meaningful in the\
+@command\{register\} and @command\{prices\} reports.\
+\
+@option\{--percentage\} (@option\{-%\}) shows account subtotals in the\
+@command\{balance\} report as percentages of the parent account.\
+\
+@option\{--totals\} include running total information in the\
+@command\{xml\} report.\
+\
+@option\{--amount-data\} (@option\{-j\}) changes the @command\{register\}\
+report so that it output nothing but the date and the value column,\
+and the latter without commodities. This is only meaningful if the\
+report uses a single commodity. This data can then be fed to other\
+programs, which could plot the date, analyze it, etc.\
+\
+@option\{--total-data\} (@option\{-J\}) changes the @command\{register\}\
+report so that it output nothing but the date and totals column,\
+without commodities.\
+\
+@option\{--display EXPR\} (@option\{-d EXPR\}) limits which postings\
+or accounts or actually displayed in a report. They might still be\
+calculated, and be part of the running total of a register report, for\
+example, but they will not be displayed. This is useful for seeing\
+last month's checking postings, against a running balance which\
+includes all posting values:\
+\
+@example\
+ledger -d "d>=[last month]" reg checking\
+@end example\
+\
+The output from this command is very different from the following,\
+whose running total includes only postings from the last month\
+onward:\
+\
+@example\
+ledger -p "last month" reg checking\
+@end example\
+\
+Which is more useful depends on what you're looking to know: the total\
+amount for the reporting range (@option\{-p\}), or simply a display\
+restricted to the reporting range (using @option\{-d\}).\
+\
+@option\{--date-format STR\} (@option\{-y STR\}) changes the basic date\
+format used by reports. The default uses a date like 2004/08/01,\
+which represents the default date format of @samp\{%Y/%m/%d\}. To\
+change the way dates are printed in general, the easiest way is to put\
+@option\{--date-format FORMAT\} in the Ledger initialization file\
+@file\{~/.ledgerrc\} (or the file referred to by @env\{LEDGER_INIT\}).\
+\
+@option\{--format STR\} (@option\{-F STR\}) sets the reporting format for\
+whatever report ledger is about to make. @xref\{Format strings\}.\
+There are also specific format commands for each report type:\
+\
+@itemize\
+@item @option\{--balance-format STR\}\
+@item @option\{--register-format STR\}\
+@item @option\{--print-format STR\}\
+@item @option\{--plot-amount-format STR\} (-j @command\{register\})\
+@item @option\{--plot-total-format STR\} (-J @command\{register\})\
+@item @option\{--equity-format STR\}\
+@item @option\{--prices-format STR\}\
+@item @option\{--wide-register-format STR\} (-w @command\{register\})\
+@end itemize} \ No newline at end of file
diff --git a/doc/Ledger.scriv/141.rtfd/TXT.rtf b/doc/Ledger.scriv/141.rtfd/TXT.rtf
new file mode 100644
index 00000000..2af93d34
--- /dev/null
+++ b/doc/Ledger.scriv/141.rtfd/TXT.rtf
@@ -0,0 +1,54 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 These options affect how commodity values are displayed:\
+\
+@option\{--price-db FILE\} sets the file that is used for recording\
+downloaded commodity prices. It is always read on startup, to\
+determine historical prices. Other settings can be placed in this\
+file manually, to prevent downloading quotes for a specific, for\
+example. This is done by adding a line like the following:\
+\
+@example\
+; Don't download quotes for the dollar, or timelog values\
+N $\
+N h\
+@end example\
+\
+@option\{--price-exp MINS\} (@option\{-L MINS\}) sets the expected\
+freshness of price quotes, in minutes. That is, if the last known\
+quote for any commodity is older than this value---and if\
+@option\{--download\} is being used---then the Internet will be\
+consulted again for a newer price. Otherwise, the old price is still\
+considered to be fresh enough.\
+\
+@option\{--download\} (@option\{-Q\}) causes quotes to be automagically\
+downloaded, as needed, by running a script named @command\{getquote\}\
+and expecting that script to return a value understood by ledger. A\
+sample implementation of a @command\{getquote\} script, implemented in\
+Perl, is provided in the distribution. Downloaded quote price are\
+then appended to the price database, usually specified using the\
+environment variable @env\{LEDGER_PRICE_DB\}.\
+\
+There are several different ways that ledger can report the totals it\
+displays. The most flexible way to adjust them is by using value\
+expressions, and the @option\{-t\} and @option\{-T\} options. However,\
+there are also several ``default'' reports, which will satisfy most\
+users basic reporting needs:\
+\
+@table @code\
+@item -O, --quantity\
+Reports commodity totals (this is the default)\
+\
+@item -B, --basis\
+Reports the cost basis for all postings.\
+\
+@item -V, --market\
+Reports the last known market value for all commodities.\
+\
+@item -G --gain\
+Reports the net gain/loss for all commodities in the report that have\
+a price history.\
+@end table} \ No newline at end of file
diff --git a/doc/Ledger.scriv/142.rtfd/TXT.rtf b/doc/Ledger.scriv/142.rtfd/TXT.rtf
new file mode 100644
index 00000000..bdfc5783
--- /dev/null
+++ b/doc/Ledger.scriv/142.rtfd/TXT.rtf
@@ -0,0 +1,18 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Every option to ledger may be set using an environment variable. If\
+an option has a long name such @option\{--this-option\}, setting the\
+environment variable @env\{LEDGER_THIS_OPTION\} will have the same\
+affect as specifying that option on the command-line. Options on the\
+command-line always take precedence over environment variable\
+settings, however.\
+\
+Note that you may also permanently specify option values by placing\
+option settings in the file @file\{~/.ledgerrc\}, for example:\
+\
+@example\
+--cache /tmp/.mycache\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/143.rtfd/TXT.rtf b/doc/Ledger.scriv/143.rtfd/TXT.rtf
new file mode 100644
index 00000000..c2fba0d8
--- /dev/null
+++ b/doc/Ledger.scriv/143.rtfd/TXT.rtf
@@ -0,0 +1,88 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 A period expression indicates a span of time, or a reporting interval,\
+or both. The full syntax is:\
+\
+@example\
+[INTERVAL] [BEGIN] [END]\
+@end example\
+\
+The optional @var\{INTERVAL\} part may be any one of:\
+\
+@example\
+every day\
+every week\
+every monthly\
+every quarter\
+every year\
+every N days # N is any integer\
+every N weeks\
+every N months\
+every N quarters\
+every N years\
+daily\
+weekly\
+biweekly\
+monthly\
+bimonthly\
+quarterly\
+yearly\
+@end example\
+\
+After the interval, a begin time, end time, both or neither may be\
+specified. As for the begin time, it can be either of:\
+\
+@example\
+from <SPEC>\
+since <SPEC>\
+@end example\
+\
+The end time can be either of:\
+\
+@example\
+to <SPEC>\
+until <SPEC>\
+@end example\
+\
+Where @var\{SPEC\} can be any of:\
+\
+@example\
+2004\
+2004/10\
+2004/10/1\
+10/1\
+october\
+oct\
+this week # or day, month, quarter, year\
+next week\
+last week\
+@end example\
+\
+The beginning and ending can be given at the same time, if it spans a\
+single period. In that case, just use @var\{SPEC\} by itself. In that\
+case, the period @samp\{oct\}, for example, will cover all the days in\
+october. The possible forms are:\
+\
+@example\
+<SPEC>\
+in <SPEC>\
+@end example\
+\
+Here are a few examples of period expressions:\
+\
+@example\
+monthly\
+monthly in 2004\
+weekly from oct\
+weekly from last month\
+from sep to oct\
+from 10/1 to 10/5\
+monthly until 2005\
+from apr\
+until nov\
+last oct\
+weekly last august\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/144.rtfd/TXT.rtf b/doc/Ledger.scriv/144.rtfd/TXT.rtf
new file mode 100644
index 00000000..fcb87424
--- /dev/null
+++ b/doc/Ledger.scriv/144.rtfd/TXT.rtf
@@ -0,0 +1,149 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Format strings may be used to change the output format of reports.\
+They are specified by passing a formatting string to the\
+@option\{--format\} (@option\{-F\}) option. Within that string,\
+constructs are allowed which make it possible to display the various\
+parts of an account or posting in custom ways.\
+\
+Within a format strings, a substitution is specified using a percent\
+character (@samp\{%\}). The basic format of all substitutions is:\
+\
+@example\
+%[-][MIN WIDTH][.MAX WIDTH]EXPR\
+@end example\
+\
+If the optional minus sign (@samp\{-\}) follows the percent character,\
+whatever is substituted will be left justified. The default is right\
+justified. If a minimum width is given next, the substituted text\
+will be at least that wide, perhaps wider. If a period and a maximum\
+width is given, the substituted text will never be wider than this,\
+and will be truncated to fit. Here are some examples:\
+\
+@example\
+%-P a transaction's payee, left justified\
+%20P The same, right justified, at least 20 chars wide\
+%.20P The same, no more than 20 chars wide\
+%-.20P Left justified, maximum twenty chars wide\
+@end example\
+\
+The expression following the format constraints can be a single\
+letter, or an expression enclosed in parentheses or brackets. The\
+allowable expressions are:\
+\
+@table @code\
+@item %\
+Inserts a percent sign.\
+\
+@item t\
+Inserts the results of the value expression specified by @option\{-t\}.\
+If @option\{-t\} was not specified, the current report style's value\
+expression is used.\
+\
+@item T\
+Inserts the results of the value expression specified by @option\{-T\}.\
+If @option\{-T\} was not specified, the current report style's value\
+expression is used.\
+\
+@item |\
+Inserts a single space. This is useful if a width is specified, for\
+inserting a certain number of spaces.\
+\
+@item _\
+Inserts a space for each level of an account's depth. That is, if an\
+account has two parents, this construct will insert two spaces. If a\
+minimum width is specified, that much space is inserted for each level\
+of depth. Thus @samp\{%5_\}, for an account with four parents, will\
+insert twenty spaces.\
+\
+@item (EXPR)\
+Inserts the amount resulting from the value expression given in\
+parentheses. To insert five times the total value of an account, for\
+example, one could say @samp\{%12(5*O)\}. Note: It's important to put\
+the five first in that expression, so that the commodity doesn't get\
+stripped from the total.\
+\
+@item [DATEFMT]\
+Inserts the result of formatting a posting's date with a date\
+format string, epostly like those supported by @code\{strftime\}. For\
+example: @samp\{%[%Y/%m/%d %H:%M:%S]\}.\
+\
+@item S\
+Insert the pathname of the file from which the transaction's data was read.\
+\
+@item B\
+Inserts the beginning character position of that transaction within the file.\
+\
+@item b\
+Inserts the beginning line of that transaction within the file.\
+\
+@item E\
+Inserts the ending character position of that transaction within the file.\
+\
+@item e\
+Inserts the ending line of that transaction within the file.\
+\
+@item D\
+By default, this is the same as @samp\{%[%Y/%m%/d]\}. The date format\
+used can be changed at any time with the @option\{-y\} flag, however.\
+Using @samp\{%D\} gives the user more control over the way dates are\
+output.\
+\
+@item d\
+This is the same as the @samp\{%D\} option, unless the transaction has an\
+effective date, in which case it prints\
+@samp\{[ACTUAL_DATE=EFFECtIVE_DATE]\}.\
+\
+@item X\
+If a posting has been cleared, this inserts @samp\{*\} followed by a\
+space; otherwise nothing is inserted.\
+\
+@item Y\
+This is the same as @samp\{%X\}, except that it only displays a state\
+character if all of the member postings have the same state.\
+\
+@item C\
+Inserts the checking number for a transaction, in parentheses, followed by\
+a space; if none was specified, nothing is inserted.\
+\
+@item P\
+Inserts the payee related to a posting.\
+\
+@item a\
+Inserts the optimal short name for an account. This is normally used\
+in balance reports. It prints a parent account's name if that name\
+has not been printed yet, otherwise it just prints the account's name.\
+\
+@item A\
+Inserts the full name of an account.\
+\
+@item W\
+This is the same as @samp\{%A\}, except that it first displays the\
+posting's state @emph\{if the transaction's posting states are not\
+all the same\}, followed by the full account name. This is offered as\
+a printing optimization, so that combined with @samp\{%Y\}, only the\
+minimum amount of state detail is printed.\
+\
+@item o\
+Inserts the ``optimized'' form of a posting's amount. This is\
+used by the print report. In some cases, this inserts nothing; in\
+others, it inserts the posting amount and its cost. It's use is\
+not recommend unless you are modifying the print report.\
+\
+@item n\
+Inserts the note associated with a posting, preceded by two spaces\
+and a semi-colon, if it exists. Thus, no none becomes an empty\
+string, while the note @samp\{foo\} is substituted as @samp\{ ; foo\}.\
+\
+@item N\
+Inserts the note associated with a posting, if one exists.\
+\
+@item /\
+The @samp\{%/\} construct is special. It separates a format string\
+between what is printed for the first posting of a transaction, and\
+what is printed for all subsequent postings. If not used, the\
+same format string is used for all postings.\
+@end table} \ No newline at end of file
diff --git a/doc/Ledger.scriv/145.rtfd/TXT.rtf b/doc/Ledger.scriv/145.rtfd/TXT.rtf
new file mode 100644
index 00000000..585c94d1
--- /dev/null
+++ b/doc/Ledger.scriv/145.rtfd/TXT.rtf
@@ -0,0 +1,52 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Value expressions are an expression language used by Ledger to\
+calculate values used by the program for many different purposes:\
+\
+@enumerate\
+@item\
+The values displayed in reports\
+@item\
+For predicates (where truth is anything non-zero), to determine which\
+postings are calculated (@option\{-l\}) or displayed (@option\{-d\}).\
+@item\
+For sorting criteria, to yield the sort key.\
+@item\
+In the matching criteria used by automated postings.\
+@end enumerate\
+\
+Value expressions support most simple math and logic operators, in\
+addition to a set of one letter functions and variables. A function's\
+argument is whatever follows it. The following is a display predicate\
+that I use with the @command\{balance\} command:\
+\
+@example\
+ledger -d /^Liabilities/?T<0:UT>100 balance\
+@end example\
+\
+The effect is that account totals are displayed only if: 1) A\
+Liabilities account has a total less than zero; or 2) the absolute\
+value of the account's total exceeds 100 units of whatever commodity\
+contains. If it contains multiple commodities, only one of them must\
+exceed 100 units.\
+\
+Display predicates are also very handy with register reports, to\
+constrain which transactions are printed. For example, the following\
+command shows only transactions from the beginning of the current month,\
+while still calculating the running balance based on all transactions:\
+\
+@example\
+ledger -d "d>[this month]" register checking\
+@end example\
+\
+This advantage to this command's complexity is that it prints the\
+running total in terms of all transactions in the register. The following,\
+simpler command is similar, but totals only the displayed\
+postings:\
+\
+@example\
+ledger -b "this month" register checking\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/146.rtfd/TXT.rtf b/doc/Ledger.scriv/146.rtfd/TXT.rtf
new file mode 100644
index 00000000..154739a9
--- /dev/null
+++ b/doc/Ledger.scriv/146.rtfd/TXT.rtf
@@ -0,0 +1,28 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Below are the one letter variables available in any value expression.\
+For the register and print commands, these variables relate to\
+individual postings, and sometimes the account affected by a\
+posting. For the balance command, these variables relate to\
+accounts---often with a subtle difference in meaning. The use of each\
+variable for both is specified.\
+\
+@table @code\
+@item t\
+This maps to whatever the user specified with @option\{-t\}. In a\
+register report, @option\{-t\} changes the value column; in a balance\
+report, it has no meaning by default. If @option\{-t\} was not\
+specified, the current report style's value expression is used.\
+\
+@item T\
+This maps to whatever the user specified with @option\{-T\}. In a\
+register report, @option\{-T\} changes the totals column; in a balance\
+report, this is the value given for each account. If @option\{-T\} was\
+not specified, the current report style's value expression is used.\
+\
+@item m\
+This is always the present moment/date.\
+@end table} \ No newline at end of file
diff --git a/doc/Ledger.scriv/147.rtfd/TXT.rtf b/doc/Ledger.scriv/147.rtfd/TXT.rtf
new file mode 100644
index 00000000..5b79b635
--- /dev/null
+++ b/doc/Ledger.scriv/147.rtfd/TXT.rtf
@@ -0,0 +1,42 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @table @code\
+@item d\
+A posting's date, as the number of seconds past the epoch. This\
+is always ``today'' for an account.\
+\
+@item a\
+The posting's amount; the balance of an account, without\
+considering children.\
+\
+@item b\
+The cost of a posting; the cost of an account, without its\
+children.\
+\
+@item v\
+The market value of a posting, or an account without its children.\
+\
+@item g\
+The net gain (market value minus cost basis), for a posting or an\
+account without its children. It is the same as @samp\{v-b\}.\
+\
+@item l\
+The depth (``level'') of an account. If an account has one parent,\
+it's depth is one.\
+\
+@item n\
+The index of a posting, or the count of postings affecting an\
+account.\
+\
+@item X\
+1 if a posting's transaction has been cleared, 0 otherwise.\
+\
+@item R\
+1 if a posting is not virtual, 0 otherwise.\
+\
+@item Z\
+1 if a posting is not automated, 0 otherwise.\
+@end table} \ No newline at end of file
diff --git a/doc/Ledger.scriv/148.rtfd/TXT.rtf b/doc/Ledger.scriv/148.rtfd/TXT.rtf
new file mode 100644
index 00000000..1ce3254a
--- /dev/null
+++ b/doc/Ledger.scriv/148.rtfd/TXT.rtf
@@ -0,0 +1,27 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @table @code\
+@item O\
+The total of all postings seen so far, or the total of an account\
+and all its children.\
+\
+@item N\
+The total count of postings affecting an account and all its\
+children.\
+\
+@item B\
+The total cost of all postings seen so far; the total cost of an\
+account and all its children.\
+\
+@item V\
+The market value of all postings seen so far, or of an account and\
+all its children.\
+\
+@item G\
+The total net gain (market value minus cost basis), for a series of\
+postings, or an account and its children. It is the same as\
+@samp\{V-B\}.\
+@end table} \ No newline at end of file
diff --git a/doc/Ledger.scriv/149.rtfd/TXT.rtf b/doc/Ledger.scriv/149.rtfd/TXT.rtf
new file mode 100644
index 00000000..f2cbbba6
--- /dev/null
+++ b/doc/Ledger.scriv/149.rtfd/TXT.rtf
@@ -0,0 +1,26 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The available one letter functions are:\
+\
+@table @code\
+@item -\
+Negates the argument.\
+\
+@item U\
+The absolute (unsigned) value of the argument.\
+\
+@item S\
+Strips the commodity from the argument.\
+\
+@item A\
+The arithmetic mean of the argument; @samp\{Ax\} is the same as\
+@samp\{x/n\}.\
+\
+@item P\
+The present market value of the argument. The syntax @samp\{P(x,d)\} is\
+supported, which yields the market value at time @samp\{d\}. If no date\
+is given, then the current moment is used.\
+@end table} \ No newline at end of file
diff --git a/doc/Ledger.scriv/15.rtfd/TXT.rtf b/doc/Ledger.scriv/15.rtfd/TXT.rtf
new file mode 100644
index 00000000..f0c50ef1
--- /dev/null
+++ b/doc/Ledger.scriv/15.rtfd/TXT.rtf
@@ -0,0 +1,14 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 If you need help on how to use Ledger, or run into problems, you can\
+just the Ledger mailing list at the following Web address:\
+\
+@example\
+https://lists.sourceforge.net/lists/listinfo/ledger-discuss\
+@end example\
+\
+You can also find help at the @samp\{#ledger\} channel on the IRC server\
+@samp\{irc.freenode.net\}.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/150.rtfd/TXT.rtf b/doc/Ledger.scriv/150.rtfd/TXT.rtf
new file mode 100644
index 00000000..ed38d688
--- /dev/null
+++ b/doc/Ledger.scriv/150.rtfd/TXT.rtf
@@ -0,0 +1,13 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The binary and ternary operators, in order of precedence, are:\
+\
+@enumerate\
+@item @samp\{* /\}\
+@item @samp\{+ -\}\
+@item @samp\{! < > =\}\
+@item @samp\{& | ?:\}\
+@end enumerate} \ No newline at end of file
diff --git a/doc/Ledger.scriv/151.rtfd/TXT.rtf b/doc/Ledger.scriv/151.rtfd/TXT.rtf
new file mode 100644
index 00000000..3f8fb5a7
--- /dev/null
+++ b/doc/Ledger.scriv/151.rtfd/TXT.rtf
@@ -0,0 +1,48 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 More complicated expressions are possible using:\
+\
+@table @code\
+@item NUM\
+A plain integer represents a commodity-less amount.\
+\
+@item @\{AMOUNT@\}\
+An amount in braces can be any kind of amount supported by ledger,\
+with or without a commodity. Use this for decimal values.\
+\
+@item /REGEXP/\
+@item W/REGEXP/\
+A regular expression that matches against an account's full name. If\
+a posting, this will match against the account affected by the\
+posting.\
+\
+@item //REGEXP/\
+@item p/REGEXP/\
+A regular expression that matches against a transaction's payee name.\
+\
+@item ///REGEXP/\
+@item w/REGEXP/\
+A regular expression that matches against an account's base name. If\
+a posting, this will match against the account affected by the\
+posting.\
+\
+@item c/REGEXP/\
+A regular expression that matches against the transaction code (the text\
+that occurs between parentheses before the payee name).\
+\
+@item e/REGEXP/\
+A regular expression that matches against a posting's note, or\
+comment field.\
+\
+@item (EXPR)\
+A sub-expression is nested in parenthesis. This can be useful passing\
+more complicated arguments to functions, or for overriding the natural\
+precedence order of operators.\
+\
+@item [DATE]\
+Useful specifying a date in plain terms. For example, you could say\
+@samp\{[2004/06/01]\}.\
+@end table} \ No newline at end of file
diff --git a/doc/Ledger.scriv/152.rtfd/TXT.rtf b/doc/Ledger.scriv/152.rtfd/TXT.rtf
new file mode 100644
index 00000000..926a552f
--- /dev/null
+++ b/doc/Ledger.scriv/152.rtfd/TXT.rtf
@@ -0,0 +1,131 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The ledger file format is quite simple, but also very flexible. It\
+supports many options, though typically the user can ignore most of\
+them. They are summarized below.\
+\
+The initial character of each line determines what the line means, and\
+how it should be interpreted. Allowable initial characters are:\
+\
+@table @code\
+@item NUMBER\
+A line beginning with a number denotes a transaction. It may be followed\
+by any number of lines, each beginning with whitespace, to denote the\
+transaction's account postings. The format of the first line is:\
+\
+@example\
+DATE[=EDATE] [*|!] [(CODE)] DESC\
+@end example\
+\
+If @samp\{*\} appears after the date (with optional effective date), it\
+indicates the transaction is ``cleared'', which can mean whatever the user\
+wants it t omean. If @samp\{!\} appears after the date, it indicates d\
+the transaction is ``pending''; i.e., tentatively cleared from the user's\
+point of view, but not yet actually cleared. If a @samp\{CODE\} appears\
+in parentheses, it may be used to indicate a check number, or the type\
+of the posting. Following these is the payee, or a description of\
+the posting.\
+\
+The format of each following posting is:\
+\
+@example\
+ ACCOUNT AMOUNT [; NOTE]\
+@end example\
+\
+The @samp\{ACCOUNT\} may be surrounded by parentheses if it is a virtual\
+postings, or square brackets if it is a virtual postings that\
+must balance. The @samp\{AMOUNT\} can be followed by a per-unit\
+posting cost, by specifying @samp\{@@ AMOUNT\}, or a complete\
+posting cost with @samp\{@@@@ AMOUNT\}. Lastly, the @samp\{NOTE\} may\
+specify an actual and/or effective date for the posting by using\
+the syntax @samp\{[ACTUAL_DATE]\} or @samp\{[=EFFECTIVE_DATE]\} or\
+@samp\{[ACTUAL_DATE=EFFECtIVE_DATE]\}.\
+\
+@item =\
+An automated transaction. A value expression must appear after the equal\
+sign.\
+\
+After this initial line there should be a set of one or more\
+postings, just as if it were normal transaction. If the amounts of the\
+postings have no commodity, they will be applied as modifiers to\
+whichever real posting is matched by the value expression.\
+\
+@item ~\
+A period transaction. A period expression must appear after the tilde.\
+\
+After this initial line there should be a set of one or more\
+postings, just as if it were normal transaction.\
+\
+@item !\
+A line beginning with an exclamation mark denotes a command directive.\
+It must be immediately followed by the command word. The supported\
+commands are:\
+\
+@table @samp\
+@item !include\
+Include the stated ledger file.\
+\
+@item !account\
+The account name is given is taken to be the parent of all\
+postings that follow, until @samp\{!end\} is seen.\
+\
+@item !end\
+Ends an account block.\
+@end table\
+\
+@item ;\
+A line beginning with a colon indicates a comment, and is ignored.\
+\
+@item Y\
+If a line begins with a capital Y, it denotes the year used for all\
+subsequent transactions that give a date without a year. The year should\
+appear immediately after the Y, for example: @samp\{Y2004\}. This is\
+useful at the beginning of a file, to specify the year for that file.\
+If all transactions specify a year, however, this command has no effect.\
+\
+@item P\
+Specifies a historical price for a commodity. These are usually found\
+in a pricing history file (see the @option\{-Q\} option). The syntax\
+is:\
+@example\
+P DATE SYMBOL PRICE\
+@end example\
+\
+@item N SYMBOL\
+Indicates that pricing information is to be ignored for a given\
+symbol, nor will quotes ever be downloaded for that symbol. Useful\
+with a home currency, such as the dollar ($). It is recommended that\
+these pricing options be set in the price database file, which\
+defaults to @file\{~/.pricedb\}. The syntax for this command is:\
+@example\
+N SYMBOL\
+@end example\
+\
+@item D AMOUNT\
+Specifies the default commodity to use, by specifying an amount in the\
+expected format. The @command\{transaction\} command will use this commodity\
+as the default when none other can be determined. This command may be\
+used multiple times, to set the default flags for different\
+commodities; whichever is seen last is used as the default commodity.\
+For example, to set US dollars as the default commodity, while also\
+setting the thousands flag and decimal flag for that commodity, use:\
+@example\
+D $1,000.00\
+@end example\
+\
+@item C AMOUNT1 = AMOUNT2\
+Specifies a commodity conversion, where the first amount is given to\
+be equivalent to the second amount. The first amount should use the\
+decimal precision desired during reporting:\
+@example\
+C 1.00 Kb = 1024 bytes\
+@end example\
+\
+@item i, o, b, h\
+These four relate to timeclock support, which permits ledger to read\
+timelog files. See the timeclock's documentation for more info on the\
+syntax of its timelog files.\
+@end table} \ No newline at end of file
diff --git a/doc/Ledger.scriv/153.rtfd/TXT.rtf b/doc/Ledger.scriv/153.rtfd/TXT.rtf
new file mode 100644
index 00000000..02b18adc
--- /dev/null
+++ b/doc/Ledger.scriv/153.rtfd/TXT.rtf
@@ -0,0 +1,45 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 This chapter presents a series of recipes, gradually introducing all of\
+the command-line features of Ledger.\
+\
+For the purpose of these examples, assume the environment variable\
+@var\{LEDGER\} is set to the file @file\{sample.dat\} (which is included\
+in the distribution), and that the contents of that file are:\
+\
+@smallexample\
+= /^Expenses:Books/\
+ (Liabilities:Taxes) -0.10\
+\
+~ Monthly\
+ Assets:Bank:Checking $500.00\
+ Income:Salary\
+\
+2004/05/01 * Checking balance\
+ Assets:Bank:Checking $1,000.00\
+ Equity:Opening Balances\
+\
+2004/05/01 * Investment balance\
+ Assets:Brokerage 50 AAPL @@ $30.00\
+ Equity:Opening Balances\
+\
+2004/05/14 * Pay day\
+ Assets:Bank:Checking $500.00\
+ Income:Salary\
+\
+2004/05/27 Book Store\
+ Expenses:Books $20.00\
+ Liabilities:MasterCard\
+\
+2004/05/27 (100) Credit card company\
+ Liabilities:MasterCard $20.00\
+ Assets:Bank:Checking\
+@end smallexample\
+\
+This sample file demonstrates a basic principle of accounting which it\
+is recommended you follow: Keep all of your accounts under five parent\
+Assets, Liabilities, Income, Expenses and Equity. It is important to\
+do so in order to make sense out of the following examples.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/155.rtfd/TXT.rtf b/doc/Ledger.scriv/155.rtfd/TXT.rtf
new file mode 100644
index 00000000..a050ecc1
--- /dev/null
+++ b/doc/Ledger.scriv/155.rtfd/TXT.rtf
@@ -0,0 +1,88 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Ledger has seven basic commands, but by far the most often used are\
+@command\{balance\} and @command\{register\}. To see a summary balance of\
+all accounts, use:\
+\
+@example\
+ledger bal\
+@end example\
+\
+@command\{bal\} is a short-hand for @command\{balance\}. This command\
+prints out the summary totals of the five parent accounts used in\
+@file\{sample.dat\}:\
+\
+@smallexample\
+ $1,480.00\
+ 50 AAPL Assets\
+ $-2,500.00 Equity\
+ $20.00 Expenses\
+ $-500.00 Income\
+ $-2.00 Liabilities\
+--------------------\
+ $-1,502.00\
+ 50 AAPL \
+@end smallexample\
+\
+None of the child accounts are shown, just the parent account totals.\
+We can see that in @samp\{Assets\} there is $1,480.00, and 50 shares of\
+Apple stock. There is also a negative grand total. Usually the grand\
+total is zero, which means that all accounts balance@footnote\{It is\
+impossible for accounts not to balance in ledger; it reports an error\
+if a posting does not balance\}. In this case, since the 50 shares\
+of Apple stock cost $1,500.00 dollars, then these two amounts balance\
+each other in the grand total. The extra $2.00 comes from a virtual\
+posting being added by the automatic transaction at the top of the file.\
+The transaction is virtual because the account name was surrounded by\
+parentheses in an automatic transaction. Automatic transactions will be\
+discussed later, but first let's remove the virtual posting from\
+the balance report by using the @option\{--real\} option:\
+\
+@example\
+ledger --real bal\
+@end example\
+\
+Now the report is:\
+\
+@smallexample\
+ $1,480.00\
+ 50 AAPL Assets\
+ $-2,500.00 Equity\
+ $20.00 Expenses\
+ $-500.00 Income\
+--------------------\
+ $-1,500.00\
+ 50 AAPL \
+@end smallexample\
+\
+Since the liability was a virtual posting, it has dropped from the\
+report and we see that final total is balanced.\
+\
+But we only know that it balances because @file\{sample.dat\} is quite\
+simple, and we happen to know that the 50 shares of Apple stock cost\
+$1,500.00. We can verify that things really balance by reporting the\
+Apple shares in terms of their cost, instead of their quantity. To do\
+this requires the @option\{--basis\}, or @option\{-B\}, option:\
+\
+@example\
+ledger --real -B bal\
+@end example\
+\
+This command reports:\
+\
+@smallexample\
+ $2,980.00 Assets\
+ $-2,500.00 Equity\
+ $20.00 Expenses\
+ $-500.00 Income\
+@end smallexample\
+\
+With the basis cost option, the grand total has disappeared, as it is\
+now zero. The confirms that the cost of everything balances to zero,\
+@emph\{which must always be true\}. Reporting the real basis cost\
+should never yield a remainder@footnote\{If it ever does, then\
+generated postings are involved, which can be removed using\
+@option\{--actual\}\}.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/156.rtfd/TXT.rtf b/doc/Ledger.scriv/156.rtfd/TXT.rtf
new file mode 100644
index 00000000..e158cd8e
--- /dev/null
+++ b/doc/Ledger.scriv/156.rtfd/TXT.rtf
@@ -0,0 +1,57 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The totals reported by the balance command are only the topmost parent\
+accounts. To see the totals of all child accounts as well, use the\
+@option\{-s\} option:\
+\
+@example\
+ledger --real -B -s bal\
+@end example\
+\
+This reports:\
+\
+@smallexample\
+ $2,980.00 Assets\
+ $1,480.00 Bank:Checking\
+ $1,500.00 Brokerage\
+ $-2,500.00 Equity:Opening Balances\
+ $20.00 Expenses:Books\
+ $-500.00 Income:Salary\
+@end smallexample\
+\
+This shows that the @samp\{Assets\} total is made up from two child\
+account, but that the total for each of the other accounts comes from\
+one child account.\
+\
+Sometimes you may have a lot of children, nested very deeply, but only\
+want to report the first two levels. This can be done with a display\
+predicate, using a value expression. In the value expression,\
+@code\{T\} represents the reported total, and @code\{l\} is the display\
+level for the account:\
+\
+@example\
+ledger --real -B -d "T&l<=2" bal\
+@end example\
+\
+This reports:\
+\
+@smallexample\
+ $2,980.00 Assets\
+ $1,480.00 Bank\
+ $1,500.00 Brokerage\
+ $-2,500.00 Equity:Opening Balances\
+ $20.00 Expenses:Books\
+ $-500.00 Income:Salary\
+@end smallexample\
+\
+Instead of reporting @samp\{Bank:Checking\} as a child of @samp\{Assets\},\
+it report only @samp\{Bank\}, since that account is a nesting level of\
+2, while @samp\{Checking\} is at level 3.\
+\
+To review the display predicate used---@code\{T&l<=2\}---this rather\
+terse expression means: Display an account only if it has a non-zero\
+total (@code\{T\}), and its nesting level is less than or equal to 2\
+(@code\{l<=2\}).} \ No newline at end of file
diff --git a/doc/Ledger.scriv/157.rtfd/TXT.rtf b/doc/Ledger.scriv/157.rtfd/TXT.rtf
new file mode 100644
index 00000000..a7632cde
--- /dev/null
+++ b/doc/Ledger.scriv/157.rtfd/TXT.rtf
@@ -0,0 +1,51 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 While reporting the totals for all accounts can be useful, most often\
+you will want to check the balance of a specific account or accounts.\
+To do this, put one or more account names after the balance command.\
+Since these names are really regular expressions, you can use partial\
+names if you wish:\
+\
+@example\
+ledger bal checking\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+ $1,480.00 Assets:Bank:Checking\
+@end smallexample\
+\
+Any number of names may be used:\
+\
+@example\
+ledger bal checking broker liab\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+ $1,480.00 Assets:Bank:Checking\
+ 50 AAPL Assets:Brokerage\
+ $-2.00 Liabilities\
+@end smallexample\
+\
+In this case no grand total is reported, because you are asking for\
+specific account balances.\
+\
+For those comfortable with regular expressions, any Perl regexp is\
+allowed:\
+\
+@example\
+ledger bal ^assets.*checking ^liab\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+ $1,480.00 Assets:Bank:Checking\
+ $-2.00 Liabilities:Taxes\
+@end smallexample} \ No newline at end of file
diff --git a/doc/Ledger.scriv/158.rtfd/TXT.rtf b/doc/Ledger.scriv/158.rtfd/TXT.rtf
new file mode 100644
index 00000000..8abfef5e
--- /dev/null
+++ b/doc/Ledger.scriv/158.rtfd/TXT.rtf
@@ -0,0 +1,70 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 While the @command\{balance\} command can be very handy for checking\
+account totals, by far the most powerful of Ledger's reporting tools\
+is the @command\{register\} command. In fact, internally both commands\
+use the same logic, but report the results differently:\
+@command\{balance\} shows the summary totals, while @command\{register\}\
+reports each posting and how it contributes to that total.\
+\
+Paradoxically, the most basic form of @command\{register\} is almost\
+never used, since it displays every posting:\
+\
+@example\
+ledger reg\
+@end example\
+\
+@command\{reg\} is a short-hand for @command\{register\}. This command\
+reports:\
+\
+@smallexample\
+2004/05/01 Checking balance Assets:Bank:Checking $1,000.00 $1,000.00\
+ Equity:Opening Balan.. $-1,000.00 0\
+2004/05/01 Investment balance Assets:Brokerage 50 AAPL 50 AAPL\
+ Equity:Opening Balan.. $-1,500.00 $-1,500.00\
+ 50 AAPL\
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $-1,000.00\
+ 50 AAPL\
+ Income:Salary $-500.00 $-1,500.00\
+ 50 AAPL\
+2004/05/27 Book Store Expenses:Books $20.00 $-1,480.00\
+ 50 AAPL\
+ Liabilities:MasterCard $-20.00 $-1,500.00\
+ 50 AAPL\
+ (Liabilities:Taxes) $-2.00 $-1,502.00\
+ 50 AAPL\
+2004/05/27 Credit card company Liabilities:MasterCard $20.00 $-1,482.00\
+ 50 AAPL\
+ Assets:Bank:Checking $-20.00 $-1,502.00\
+ 50 AAPL\
+@end smallexample\
+\
+This rather verbose output shows every account posting in\
+@file\{sample.dat\}, and how it affects the running total. The final\
+total is identical to what we saw with the plain @command\{balance\}\
+command. To see how things really balance, we can use @samp\{--real\
+-B\}, just as we did with @command\{balance\}:\
+\
+@example\
+ledger --real -B reg\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/01 Checking balance Assets:Bank:Checking $1,000.00 $1,000.00\
+ Equity:Opening Balan.. $-1,000.00 0\
+2004/05/01 Investment balance Assets:Brokerage $1,500.00 $1,500.00\
+ Equity:Opening Balan.. $-1,500.00 0\
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $500.00\
+ Income:Salary $-500.00 0\
+2004/05/27 Book Store Expenses:Books $20.00 $20.00\
+ Liabilities:MasterCard $-20.00 0\
+2004/05/27 Credit card company Liabilities:MasterCard $20.00 $20.00\
+ Assets:Bank:Checking $-20.00 0\
+@end smallexample\
+\
+Here we see that everything balances to zero in the end, as it must.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/159.rtfd/TXT.rtf b/doc/Ledger.scriv/159.rtfd/TXT.rtf
new file mode 100644
index 00000000..c34241a4
--- /dev/null
+++ b/doc/Ledger.scriv/159.rtfd/TXT.rtf
@@ -0,0 +1,37 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The most common use of the register command is to summarize\
+postings based on the account(s) they affect. Using\
+@file\{sample.dat\} as as example, we could look at all book purchases\
+using:\
+\
+@example\
+ledger reg books\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/29 Book Store Expenses:Books $20.00 $20.00\
+@end smallexample\
+\
+If a double-dash (@samp\{--\}) occurs in the list of regular\
+expressions, any following arguments are matched against payee names,\
+instead of account names:\
+\
+@example\
+ledger reg ^liab -- credit\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/29 Credit card company Liabilities:MasterCard $20.00 $20.00\
+@end smallexample\
+\
+There are many reporting options for tailoring which postings are\
+found, and also how to summarize the various amounts and totals that\
+result. These are plumbed in greater depth below.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/16.rtfd/TXT.rtf b/doc/Ledger.scriv/16.rtfd/TXT.rtf
new file mode 100644
index 00000000..af6aadd2
--- /dev/null
+++ b/doc/Ledger.scriv/16.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter Quick Reference} \ No newline at end of file
diff --git a/doc/Ledger.scriv/160.rtfd/TXT.rtf b/doc/Ledger.scriv/160.rtfd/TXT.rtf
new file mode 100644
index 00000000..e89cfe61
--- /dev/null
+++ b/doc/Ledger.scriv/160.rtfd/TXT.rtf
@@ -0,0 +1,12 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Although the easiest way to use the register is to report all the\
+postings affecting a set of accounts, it can often result in more\
+information than you want. To cope with an ever-growing amount of\
+data, there are several options which can help you pinpoint your\
+report to epostly the postings that interest you most. This is\
+called the ``calculation'' phase of Ledger. All of its related\
+options are documented under @option\{--help-calc\}.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/161.rtfd/TXT.rtf b/doc/Ledger.scriv/161.rtfd/TXT.rtf
new file mode 100644
index 00000000..f13e97b0
--- /dev/null
+++ b/doc/Ledger.scriv/161.rtfd/TXT.rtf
@@ -0,0 +1,93 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @c -c, --current show only current and past transactions (not future)\
+\
+@option\{--current\}(@option\{-c\}) displays transactions occurring on or\
+before the current date. Any transaction recorded for a future date will be\
+ignored, as if it had not been seen. This is useful if you happen to\
+pre-record transactions, but still wish to view your balances in terms of\
+what is available today.\
+\
+@c -b, --begin DATE set report begin date\
+@c -e, --end DATE set report end date\
+\
+@option\{--begin DATE\} (@option\{-b DATE\}) limits the report to only\
+those transactions occurring on or after @var\{DATE\}. The running total in\
+the register will start at zero with the first posting, even if\
+there are earlier transactions.\
+\
+To limit the display only, but still add earlier postings to the\
+running total, use the display expression @samp\{-d 'd>=[DATE]'\}):\
+\
+@example\
+ledger --basis -b may -d 'd>=[5/14]' reg ^assets\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $3,000.00\
+2004/05/27 Credit card company Assets:Bank:Checking $-20.00 $2,980.00\
+@end smallexample\
+\
+In this example, the displayed postings start from @samp\{5/14\},\
+but the calculated total starts from the beginning of @samp\{may\}.\
+\
+@option\{--end DATE\} (@option\{-e DATE\}) states when reporting should\
+end, both calculation and display. The ending date is inclusive.\
+\
+The @var\{DATE\} argument to the @option\{-b\} and @option\{-e\} options can\
+be rather flexible. Assuming the current date to be November 15,\
+2004, then all of the following are equivalent:\
+\
+@example\
+ledger -b oct bal\
+ledger -b "this oct" bal\
+ledger -b 2004/10 bal\
+ledger -b 10 bal\
+ledger -b last bal\
+ledger -b "last month" bal\
+@end example\
+\
+@c -p, --period STR report using the given period\
+@c --period-sort EXPR sort each report period's transactions by EXPR\
+\
+To constrain the report to a specific time period, use\
+@option\{--period\} (@option\{-p\}). A time period may have both a\
+beginning and an end, or neither, as well as a specified interval.\
+Here are a few examples:\
+\
+@example\
+ledger -p 2004 bal\
+ledger -p august bal\
+ledger -p "from aug to oct" bal\
+ledger -p "daily from 8/1 to 8/15" bal\
+ledger -p "weekly since august" bal\
+ledger -p "monthly from feb to oct" bal\
+ledger -p "quarterly in 2004" bal\
+ledger -p yearly bal\
+@end example\
+\
+See @ref\{Period expressions\} for more on syntax. Also, all of the\
+options @option\{-b\}, @option\{-e\} and @option\{-p\} may be used together,\
+but whatever information occurs last takes priority. An example of\
+such usage (in a script, perhaps) would be:\
+\
+@example\
+ledger -b 2004 -e 2005 -p monthly reg ^expenses\
+@end example\
+\
+This command is identical to:\
+\
+@example\
+ledger -p "monthly in 2004" reg ^expenses\
+@end example\
+\
+The postings within a period may be sorted using\
+@option\{--period-sort\}, which takes a value expression. This is\
+similar to the @option\{--sort\} option, except that it sorts within\
+each period transaction, rather than sorting all postings in the report.\
+See the documentation on @option\{--sort\} below for more details.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/162.rtfd/TXT.rtf b/doc/Ledger.scriv/162.rtfd/TXT.rtf
new file mode 100644
index 00000000..d21a5ed7
--- /dev/null
+++ b/doc/Ledger.scriv/162.rtfd/TXT.rtf
@@ -0,0 +1,46 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 By default, all regular postings are included in each report. To\
+limit the report to certain kinds of postings, use one or more of\
+the following options:\
+\
+@table @option\
+@item -C, --cleared\
+Consider only cleared postings.\
+@item -U, --uncleared\
+Consider only uncleared and pending postings.\
+@item -R, --real\
+Consider only real (non-virtual) postings.\
+@item -L, --actual\
+Consider only actual (non-automated) postings.\
+@end table\
+\
+Cleared postings are indicated by an asterix placed just before\
+the payee name in a posting. The meaning of this flag is up to\
+the user, but typically it means that a transaction has been seen on a\
+financial statement. Pending postings use an exclamation mark in\
+the same position, but are mainly used only by reconciling software.\
+Uncleared postings are for things like uncashed checks, credit\
+charges that haven't appeared on a statement yet, etc.\
+\
+Real postings are all non-virtual postings, where the account\
+name is not surrounded by parentheses or square brackets. Virtual\
+postings are useful for showing a transfer of money that never\
+really happened, like money set aside for savings without actually\
+transferring it from the parent account.\
+\
+Actual postings are those not generated, either as part of an\
+automated transaction, or a budget or forecast report. A useful of when you\
+might like to filter out generated postings is with a budget:\
+\
+@example\
+ledger --budget --actual reg ^expenses\
+@end example\
+\
+This command outputs all postings affecting a budgeted account,\
+but without subtracting the budget amount (because the generated\
+postings are suppressed with @option\{--actual\}). The report shows\
+how much you actually spent on budgeted items.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/164.rtfd/TXT.rtf b/doc/Ledger.scriv/164.rtfd/TXT.rtf
new file mode 100644
index 00000000..ede93468
--- /dev/null
+++ b/doc/Ledger.scriv/164.rtfd/TXT.rtf
@@ -0,0 +1,35 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @c -r, --related calculate report using related postings\
+\
+Normally, a register report includes only the postings that match\
+the regular expressions specified after the command word. For\
+example, to report all expenses:\
+\
+@example\
+ledger reg ^expenses\
+@end example\
+\
+This reports:\
+\
+@smallexample\
+2004/05/29 Book Store Expenses:Books $20.00 $20.00\
+@end smallexample\
+\
+Using @option\{--related\} (@option\{-r\}) reports the postings that\
+did not match your query, but only in transactions that otherwise would\
+have matched. This has the effect of indicating where money came\
+from, or when to:\
+\
+@example\
+ledger -r reg ^expenses\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/29 Book Store Liabilities:MasterCard $20.00 $20.00\
+@end smallexample} \ No newline at end of file
diff --git a/doc/Ledger.scriv/165.rtfd/TXT.rtf b/doc/Ledger.scriv/165.rtfd/TXT.rtf
new file mode 100644
index 00000000..9b5b393f
--- /dev/null
+++ b/doc/Ledger.scriv/165.rtfd/TXT.rtf
@@ -0,0 +1,102 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @c --budget generate budget transactions based on FILE\
+\
+There is more information about budgeting and forecasting in\
+@ref\{Budgeting and forecasting\}. Basically, if you have any period\
+transactions in your ledger file, you can use these options. A period\
+transaction looks like:\
+\
+@example\
+~ Monthly\
+ Assets:Bank:Checking $500.00\
+ Income:Salary\
+@end example\
+\
+The difference from a regular transaction is that the first line begins with\
+a tilde (~), and instead of a payee there's a period expression\
+(@ref\{Period expressions\}). Otherwise, a period transaction is in every\
+other way the same as a regular transaction.\
+\
+With such a transaction in your ledger file, the @option\{--budget\} option\
+will report only postings that match a budgeted account. Using\
+@file\{sample.dat\} from above:\
+\
+@example\
+ledger --budget reg ^income\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/01 Budget transaction Income:Salary $500.00 $500.00\
+2004/05/14 Pay day Income:Salary $-500.00 0\
+@end smallexample\
+\
+The final total is zero, indicating that the budget matched epostly\
+for the reported period. Budgeting is most often helpful with period\
+reporting; for example, to show monthly budget results use\
+@option\{--budget -p monthly\}.\
+\
+@c --add-budget show all postings plus the budget\
+@c --unbudgeted show only unbudgeted postings\
+\
+The @option\{--add-budget\} option reports all matching postings in\
+addition to budget postings; while @option\{--unbudgeted\} shows\
+only those that don't match a budgeted account. To summarize:\
+\
+@table @option\
+@item --budget\
+Show postings matching budgeted accounts.\
+@item --unbudgeted\
+Show postings matching unbudgeted accounts.\
+@item --add-budget\
+Show both budgeted and unbudgeted postings together (i.e., add the\
+generated budget postings to the regular report).\
+@end table\
+\
+@c --forecast EXPR generate forecast transactions while EXPR is true\
+\
+A report with the @option\{--forecast\} option will add budgeted\
+postings while the specified value expression is true. For\
+example:\
+\
+@example\
+ledger --forecast 'd<[2005] reg ^income\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/14 Pay day Income:Salary $-500.00 $-500.00\
+2004/12/01 Forecast transaction Income:Salary $-500.00 $-1,000.00\
+2005/01/01 Forecast transaction Income:Salary $-500.00 $-1,500.00\
+@end smallexample\
+\
+The date this report was made was November 5, 2004; the reason the\
+first forecast transaction is in december is that forecast transactions are only\
+added for the future, and they only stop after the value expression\
+has matched at least once, which is why the January transaction appears. A\
+forecast report can be very useful for determining when money will run\
+out in an account, or for projecting future cash flow:\
+\
+@example\
+ledger --forecast 'd<[2008]' -p yearly reg ^inc ^exp\
+@end example\
+\
+This reports balances projected income against projected expenses,\
+showing the resulting total in yearly intervals until 2008. For the\
+case of @file\{sample.dat\}, which has no budgeted expenses, the result\
+of the above command (in November 2004) is:\
+\
+@smallexample\
+2004/01/01 - 2004/12/31 Income:Salary $-1,000.00 $-1,000.00\
+ Expenses:Books $20.00 $-980.00\
+2005/01/01 - 2005/12/31 Income:Salary $-6,000.00 $-6,980.00\
+2006/01/01 - 2006/12/31 Income:Salary $-6,000.00 $-12,980.00\
+2007/01/01 - 2007/12/31 Income:Salary $-6,000.00 $-18,980.00\
+2008/01/01 - 2008/01/01 Income:Salary $-500.00 $-19,480.00\
+@end smallexample} \ No newline at end of file
diff --git a/doc/Ledger.scriv/166.rtfd/TXT.rtf b/doc/Ledger.scriv/166.rtfd/TXT.rtf
new file mode 100644
index 00000000..98ebef2d
--- /dev/null
+++ b/doc/Ledger.scriv/166.rtfd/TXT.rtf
@@ -0,0 +1,42 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @c -l, --limit EXPR calculate only postings matching EXPR\
+\
+Value expressions can be quite complex, and are treated more fully in\
+@ref\{Value expressions\}. They can be used for limiting a report with\
+@option\{--limit\} (@option\{-l\}). The following command report income\
+since august, but expenses since october:\
+\
+@example\
+ledger -l '(/income/&d>=[aug])|(/expenses/&d>=[oct])' reg\
+@end example\
+\
+The basic form of this value expression is @samp\{(A&B)|(A&B)\}. The\
+@samp\{A\} in each part matches against an account name with\
+@samp\{/name/\}, while each @samp\{B\} part compares the date of the\
+posting (@samp\{d\}) with a specified month. The resulting report\
+will contain only postings which match the value expression.\
+\
+@c -t, --amount EXPR use EXPR to calculate the displayed amount\
+@c -T, --total EXPR use EXPR to calculate the displayed total\
+\
+Another use of value expressions is to calculate the amount reported\
+for each line of a register report, or for computing the subtotal of\
+each account shown in a balance report. This example divides each\
+posting amount by two:\
+\
+@example\
+ledger -t 'a/2' reg ^exp\
+@end example\
+\
+The @option\{-t\} option doesn't affect the running total, only how the\
+posting amount is displayed. To change the running total, use\
+@option\{-T\}. In that case, you will likely want to use the total\
+(@samp\{O\}) instead of the amount (@samp\{a\}):\
+\
+@example\
+ledger -T 'O/2' reg ^exp\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/168.rtfd/TXT.rtf b/doc/Ledger.scriv/168.rtfd/TXT.rtf
new file mode 100644
index 00000000..deb76a2a
--- /dev/null
+++ b/doc/Ledger.scriv/168.rtfd/TXT.rtf
@@ -0,0 +1,11 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Even after filtering down your data to just the postings you're\
+interested in, the default reporting method of one posting per\
+line is often still too much. To combat this complexity, it is\
+possible to ask Ledger to report the details to you in many different\
+forms, summarized in various ways. This is the ``display'' phase of\
+Ledger, and is documented under @option\{--help-disp\}.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/169.rtfd/TXT.rtf b/doc/Ledger.scriv/169.rtfd/TXT.rtf
new file mode 100644
index 00000000..32ad1f32
--- /dev/null
+++ b/doc/Ledger.scriv/169.rtfd/TXT.rtf
@@ -0,0 +1,108 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @c -n, --collapse register: collapse transactions with multiple postings\
+\
+When multiple postings relate to a single transaction, they are reported\
+as part of that transaction. For example, in the case of @file\{sample.dat\}:\
+\
+@example\
+ledger reg -- book\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/29 Book Store Expenses:Books $20.00 $20.00\
+ Liabilities:MasterCard $-20.00 0\
+ (Liabilities:Taxes) $-2.00 $-2.00\
+@end smallexample\
+\
+All three postings are part of one transaction, and as such the transaction\
+details are printed only once. To report every transaction on a single\
+line, use @option\{-n\} to collapse transactions with multiple postings:\
+\
+@example\
+ledger -n reg -- book\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/29 Book Store <Total> $-2.00 $-2.00\
+@end smallexample\
+\
+In the balance report, @option\{-n\} causes the grand total not to be\
+displayed at the bottom of the report.\
+\
+@c -s, --subtotal balance: show sub-accounts; other: show subtotals\
+\
+If an account occurs more than once in a report, it is possible to\
+combine them all and report the total per-account, using @option\{-s\}.\
+For example, this command:\
+\
+@example\
+ledger -B reg ^assets\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/01 Checking balance Assets:Bank:Checking $1,000.00 $1,000.00\
+2004/05/01 Investment balance Assets:Brokerage $1,500.00 $2,500.00\
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $3,000.00\
+2004/05/27 Credit card company Assets:Bank:Checking $-20.00 $2,980.00\
+@end smallexample\
+\
+But if the @option\{-s\} option is added, the result becomes:\
+\
+@smallexample\
+2004/05/01 - 2004/05/29 Assets:Bank:Checking $1,480.00 $1,480.00\
+ Assets:Brokerage $1,500.00 $2,980.00\
+@end smallexample\
+\
+When account subtotaling is used, only one transaction is printed, and the\
+date and name reflect the range of the combined postings.\
+\
+@c -P, --by-payee show summarized totals by payee\
+\
+With @option\{-P\}, postings relating to the same payee are\
+combined. In this case, the date of the combined transaction is that of the\
+latest posting.\
+\
+@c -x, --comm-as-payee set commodity name as the payee, for reporting\
+\
+@option\{-x\} changes the payee name for each posting to be the same\
+as the commodity it uses. This can be especially useful combined with\
+other options, like @option\{-P\}. For example:\
+\
+@example\
+ledger -Px reg ^assets\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/29 $ Assets:Bank:Checking $1,480.00 $1,480.00\
+2004/05/01 AAPL Assets:Brokerage 50 AAPL $1,480.00\
+ 50 AAPL\
+@end smallexample\
+\
+This reports shows the subtotal for each commodity held, and where it\
+is located. To see the basis cost, or initial investment, add\
+@option\{-B\}. Applied to the example above:\
+\
+@smallexample\
+2004/05/29 $ Assets:Bank:Checking $1,480.00 $1,480.00\
+2004/05/01 AAPL Assets:Brokerage $1,500.00 $2,980.00\
+@end smallexample\
+\
+@c -E, --empty balance: show accounts with zero balance\
+\
+The only other options which affect summarized totals is @option\{-E\},\
+which works only in the balance report. In this case, it shows\
+matching accounts with a zero a balance, which are ordinarily\
+excluded. This can be useful to see all the accounts involved in a\
+report, even if some have no total.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/17.rtfd/TXT.rtf b/doc/Ledger.scriv/17.rtfd/TXT.rtf
new file mode 100644
index 00000000..6eec3f00
--- /dev/null
+++ b/doc/Ledger.scriv/17.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter Ledger Tutorial} \ No newline at end of file
diff --git a/doc/Ledger.scriv/170.rtfd/TXT.rtf b/doc/Ledger.scriv/170.rtfd/TXT.rtf
new file mode 100644
index 00000000..f7f2899e
--- /dev/null
+++ b/doc/Ledger.scriv/170.rtfd/TXT.rtf
@@ -0,0 +1,35 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Although the @option\{-p\} option (also @option\{--period\}) is much more\
+versatile, there are other options to make the most common period\
+reports easier:\
+\
+@table @option\
+@item -W, --weekly\
+Show weekly sub-totals. Same as @samp\{-p weekly\}.\
+@item -M, --monthly\
+Show monthly sub-totals. Same as @samp\{-p monthly\}.\
+@item -Y, --yearly\
+Show yearly sub-totals. Same as @samp\{-p yearly\}.\
+@end table\
+\
+@c --dow show a days-of-the-week report\
+\
+There is one kind of period report cannot be done with @option\{-p\}.\
+This is the @option\{--dow\}, or ``days of the week'' report, which\
+shows summarized totals for each day of the week. The following\
+examples shows a ``day of the week'' report of income and expenses:\
+\
+@example\
+ledger --dow reg ^inc ^exp\
+@end example\
+\
+Reports:\
+\
+@smallexample\
+2004/05/27 Thursdays Expenses:Books $20.00 $20.00\
+2004/05/14 Fridays Income:Salary $-500.00 $-480.00\
+@end smallexample} \ No newline at end of file
diff --git a/doc/Ledger.scriv/171.rtfd/TXT.rtf b/doc/Ledger.scriv/171.rtfd/TXT.rtf
new file mode 100644
index 00000000..ce6a4c2f
--- /dev/null
+++ b/doc/Ledger.scriv/171.rtfd/TXT.rtf
@@ -0,0 +1,59 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @c -S, --sort EXPR sort report according to the value expression EXPR\
+\
+The postings displayed in a report are shown in the same order as\
+they appear in the ledger file. To change the order and sort a\
+report, use the @option\{--sort\} option. @option\{--sort\} takes a value\
+expression to determine the value to sort against, making it possible\
+to sort according to complex criteria. Here are some simple and\
+useful examples:\
+\
+@example\
+ledger --sort d reg ^exp # sort by date\
+ledger --sort t reg ^exp # sort by amount total\
+ledger --sort -t reg ^exp # reverse sort by amount total\
+ledger --sort Ut reg ^exp # sort by abs amount total\
+@end example\
+\
+For the balance report, you will want to use @samp\{T\} instead of\
+@samp\{t\}:\
+\
+@example\
+ledger --sort T reg ^exp # sort by amount total\
+ledger --sort -T reg ^exp # reverse sort by amount total\
+ledger --sort UT reg ^exp # sort by abs amount total\
+@end example\
+\
+The @option\{--sort\} options sorts all postings in a report. If\
+periods are used (such as @option\{--monthly\}), this can get somewhat\
+confusing. In that case, you'll probably want to sort within periods\
+using @option\{--period-sort\} instead of @option\{--sort\}.\
+\
+@c -w, --wide for the default register report, use 132 columns\
+\
+And if the register seems too cramped, and you have a lot of screen\
+real estate, you can use @option\{-w\} to format the report within 132\
+acolumns, instead of 80. You are more likely then to see full payee\
+and account names, as well as properly formatted totals when\
+long-named commodities are used.\
+\
+If you want only the first or last N transactions to be printed---which can\
+be very useful for viewing the last 10 transactions in your checking\
+account, while also showing the cumulative balance from all\
+transactions---use the @option\{--head\} and/or @option\{--tail\} options. The\
+two options may be used simultaneously, for example:\
+\
+@example\
+ledger --tail 20 reg checking\
+@end example\
+\
+If the output from your command is very long, Ledger can output the\
+data to a pager utility, such as @command\{more\} or @command\{less\}:\
+\
+@example\
+ledger --pager /usr/bin/less reg checking\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/172.rtfd/TXT.rtf b/doc/Ledger.scriv/172.rtfd/TXT.rtf
new file mode 100644
index 00000000..56ff06a0
--- /dev/null
+++ b/doc/Ledger.scriv/172.rtfd/TXT.rtf
@@ -0,0 +1,47 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @c -A, --average report average posting amount\
+\
+To see the running total changed to a running average, use\
+@option\{-A\}. The final posting's total will be the overall\
+average of all displayed postings. The works in conjunction with\
+period reporting, so that you can see your monthly average expenses\
+with:\
+\
+@example\
+ledger -AM reg ^expenses:food\
+ledger -AMn reg ^expenses\
+@end example\
+\
+This works in the balance report too:\
+\
+@example\
+ledger -AM bal ^expenses:food\
+ledger -AMs bal ^expenses\
+@end example\
+\
+@c -D, --deviation report deviation from the average\
+\
+The @option\{-D\} option changes the running average into a deviation\
+from the running average. This only makes sense in the register\
+report, however.\
+\
+@example\
+ledger -DM reg ^expenses:food\
+@end example\
+\
+@c -%, --percentage report balance totals as a percentile of the parent\
+\
+In the balance report only, @option\{-%\} changes the reported totals\
+into a percentage of the parent account. This kind of report is\
+confusing if negative amounts are involved, and doesn't work at all if\
+multiple commodities occur in an account's history. It has a somewhat\
+limited usefulness, therefore, but in certain cases it can be handy,\
+such as reviewing overall expenses:\
+\
+@example\
+ledger -%s -S T bal ^expenses\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/173.rtfd/TXT.rtf b/doc/Ledger.scriv/173.rtfd/TXT.rtf
new file mode 100644
index 00000000..6fe19c0b
--- /dev/null
+++ b/doc/Ledger.scriv/173.rtfd/TXT.rtf
@@ -0,0 +1,19 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @c --totals in the "xml" report, include running total\
+\
+Normally in the @command\{xml\} report, only posting amounts are\
+printed. To include the running total under a @samp\{<total>\} tag, use\
+@option\{--totals\}. This does not affect any other report.\
+\
+@c -j, --amount-data print only raw amount data (useful for scripting)\
+@c -J, --total-data print only raw total data\
+\
+In the register report only, the output can be changed with\
+@option\{-j\} to show only the date and the amount---without\
+commodities. This only makes sense if a single commodity appears in\
+the report, but can be quite useful for scripting, or passing the data\
+to Gnuplot. To show only the date and running total, use @option\{-J\}.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/174.rtfd/TXT.rtf b/doc/Ledger.scriv/174.rtfd/TXT.rtf
new file mode 100644
index 00000000..74b0175b
--- /dev/null
+++ b/doc/Ledger.scriv/174.rtfd/TXT.rtf
@@ -0,0 +1,19 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @c -d, --display EXPR display only postings matching EXPR\
+\
+With @option\{-d\} you can decide which postings (or accounts in the\
+balance report) are displayed, according to a value expression. The\
+computed total is not affected, only the display. This can be very\
+useful for shortening a report without changing the running total:\
+\
+@example\
+ledger -d 'd>=[last month]' reg checking\
+@end example\
+\
+This command shows the checking account's register, beginning from\
+last month, but with the running total reflecting the entire history\
+of the account.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/175.rtfd/TXT.rtf b/doc/Ledger.scriv/175.rtfd/TXT.rtf
new file mode 100644
index 00000000..9d6e5cb7
--- /dev/null
+++ b/doc/Ledger.scriv/175.rtfd/TXT.rtf
@@ -0,0 +1,74 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @c -y, --date-format STR use STR as the date format (default: %Y/%m/%d)\
+\
+When dates are printed in any report, the default format is\
+@samp\{%Y/%m/%d\}, which yields dates of the form @samp\{YYYY/mm/dd\}.\
+This can be changed with @option\{-y\}, whose argument is a\
+@code\{strftime\} string---see your system's C library documentation for\
+the allowable codes. Mostly you will want to use @samp\{%Y\}, @samp\{%m\}\
+and @samp\{%d\}, in whatever combination is convenient for your locale.\
+\
+@c -F, --format STR use STR as the format; for each report type, use:\
+@c --balance-format --register-format --print-format\
+@c --plot-amount-format --plot-total-format --equity-format\
+@c --prices-format --wide-register-format\
+\
+To change the format of the entire reported line, use @option\{-F\}. It\
+supports quite a large number of options, which are all documented in\
+@ref\{Format strings\}. In addition, each specific kind of report\
+(except for @command\{xml\}) can be changed using one of the following\
+options:\
+\
+@table @option\
+@item --balance-format\
+@command\{balance\} report. Default:\
+@smallexample\
+%20T %2_%-a\\n\
+@end smallexample\
+\
+@item --register-format\
+@command\{register\} report. Default:\
+@smallexample\
+%D %-.20P %-.22A %12.66t %12.80T\\n%/%32|%-.22A %12.66t %12.80T\\n\
+@end smallexample\
+\
+@item --print-format\
+@command\{print\} report. Default:\
+@smallexample\
+%D %-.35P %-.38A %22.108t %22.132T\\n%/%48|%-.38A %22.108t %22.132T\\n\
+@end smallexample\
+\
+@item --plot-amount-format\
+@command\{register\} report when @option\{-j\} (plot amount) is used. Default:\
+@smallexample\
+%D %(St)\\n\
+@end smallexample\
+\
+@item --plot-total-format\
+@command\{register\} report when @option\{-J\} (plot total) is used. Default:\
+@smallexample\
+%D %(ST)\\n\
+@end smallexample\
+\
+@item --equity-format\
+@command\{equity\} report. Default:\
+@smallexample\
+\\n%D %Y%C%P\\n %-34W %12o%n\\n%/ %-34W %12o%n\\n\
+@end smallexample\
+\
+@item --prices-format\
+@command\{prices\} report. Default:\
+@smallexample\
+\\n%D %Y%C%P\\n%/ %-34W %12t\\n\
+@end smallexample\
+\
+@item --wide-register-format\
+@command\{register\} report when @option\{-w\} (wide) is used. Default:\
+@smallexample\
+%D %-.35P %-.38A %22.108t %22.132T\\n%/%48|%-.38A %22.108t %22.132T\\n\
+@end smallexample\
+@end table} \ No newline at end of file
diff --git a/doc/Ledger.scriv/176.rtfd/TXT.rtf b/doc/Ledger.scriv/176.rtfd/TXT.rtf
new file mode 100644
index 00000000..0f82bc4e
--- /dev/null
+++ b/doc/Ledger.scriv/176.rtfd/TXT.rtf
@@ -0,0 +1,44 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 If your ledger file uses the standard top-level accounts: Assets,\
+Liabilities, Income, Expenses, Equity: then the following queries will\
+enable you to generate some typical accounting reports from your data.\
+\
+Your @emph\{net worth\} can be determined by balancing assets against\
+liabilities:\
+\
+@example\
+ledger bal ^assets ^liab\
+@end example\
+\
+By removing long-term investment and loan accounts, you can see your\
+current net liquidity (or liquid net worth):\
+\
+@example\
+ledger bal ^assets ^liab -retirement -brokerage -loan\
+@end example\
+\
+Balancing expenses against income yields your @emph\{cash flow\}, or net\
+profit/loss:\
+\
+@example\
+ledger bal ^exp ^inc\
+@end example\
+\
+In this case, if the number is positive it means you spent more than\
+you earned during the report period.\
+\
+@c ----------------------------------------------------------------------\
+\
+The most often used command is the ``balance'' command:\
+\
+@example\
+export LEDGER=/home/johnw/doc/ledger.dat\
+ledger balance\
+@end example\
+\
+Here I've set my Ledger environment variable to point to where my\
+ledger file is hiding. Thereafter, I needn't specify it again.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/177.rtfd/TXT.rtf b/doc/Ledger.scriv/177.rtfd/TXT.rtf
new file mode 100644
index 00000000..5472661e
--- /dev/null
+++ b/doc/Ledger.scriv/177.rtfd/TXT.rtf
@@ -0,0 +1,36 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The balance command prints out the summarized balances of all my\
+top-level accounts, excluding sub-accounts. In order to see the\
+balances for a specific account, just specify a regular expression\
+after the balance command:\
+\
+@example\
+ledger balance expenses:food\
+@end example\
+\
+This will show all the money that's been spent on food, since the\
+beginning of the ledger. For food spending just this month\
+(September), use:\
+\
+@example\
+ledger -p sep balance expenses:food\
+@end example\
+\
+Or maybe you want to see all of your assets, in which case the -s\
+(show sub-accounts) option comes in handy:\
+\
+@example\
+ledger -s balance ^assets\
+@end example\
+\
+To exclude a particular account, use a regular expression with a\
+leading minus sign. The following will show all expenses, but without\
+food spending:\
+\
+@example\
+ledger balance expenses -food\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/178.rtfd/TXT.rtf b/doc/Ledger.scriv/178.rtfd/TXT.rtf
new file mode 100644
index 00000000..7cefa21c
--- /dev/null
+++ b/doc/Ledger.scriv/178.rtfd/TXT.rtf
@@ -0,0 +1,7 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 There is no built-in way to report posting amounts or account\
+balances in terms of percentages.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/18.rtfd/TXT.rtf b/doc/Ledger.scriv/18.rtfd/TXT.rtf
new file mode 100644
index 00000000..fd119646
--- /dev/null
+++ b/doc/Ledger.scriv/18.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter Ledger in Practice} \ No newline at end of file
diff --git a/doc/Ledger.scriv/180.rtfd/TXT.rtf b/doc/Ledger.scriv/180.rtfd/TXT.rtf
new file mode 100644
index 00000000..05c12f95
--- /dev/null
+++ b/doc/Ledger.scriv/180.rtfd/TXT.rtf
@@ -0,0 +1,51 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Accountants will talk of ``credits'' and ``debits'', but the meaning\
+is often different from the layman's understanding. To avoid\
+confusion, Ledger uses only subtractions and additions, although the\
+underlying intent is the same as standard accounting principles.\
+\
+Recall that every posting will involve two or more accounts.\
+Money is transferred from one or more accounts to one or more other\
+accounts. To record the posting, an amount is @emph\{subtracted\}\
+from the source accounts, and @emph\{added\} to the target accounts.\
+\
+In order to write a Ledger transaction correctly, you must determine where\
+the money comes from and where it goes to. For example, when you are\
+paid a salary, you must add money to your bank account and also\
+subtract it from an income account:\
+\
+@smallexample\
+9/29 My Employer\
+ Assets:Checking $500.00\
+ Income:Salary $-500.00\
+@end smallexample\
+\
+Why is the Income a negative figure? When you look at the balance\
+totals for your ledger, you may be surprised to see that Expenses are\
+a positive figure, and Income is a negative figure. It may take some\
+getting used to, but to properly use a general ledger you must think\
+in terms of how money moves. Rather than Ledger ``fixing'' the minus\
+signs, let's understand why they are there.\
+\
+When you earn money, the money has to come from somewhere. Let's call\
+that somewhere ``society''. In order for society to give you an\
+income, you must take money away (withdraw) from society in order to\
+put it into (make a payment to) your bank. When you then spend that\
+money, it leaves your bank account (a withdrawal) and goes back to\
+society (a payment). This is why Income will appear negative---it\
+reflects the money you have drawn from society---and why Expenses will\
+be positive---it is the amount you've given back. These additions and\
+subtractions will always cancel each other out in the end, because you\
+don't have the ability to create new money: it must always come from\
+somewhere, and in the end must always leave. This is the beginning of\
+economy, after which the explanation gets terribly difficult.\
+\
+Based on that explanation, here's another way to look at your balance\
+report: every negative figure means that that account or person or\
+place has less money now than when you started your ledger; and every\
+positive figure means that that account or person or place has more\
+money now that when you started your ledger. Make sense?} \ No newline at end of file
diff --git a/doc/Ledger.scriv/181.rtfd/TXT.rtf b/doc/Ledger.scriv/181.rtfd/TXT.rtf
new file mode 100644
index 00000000..f3354765
--- /dev/null
+++ b/doc/Ledger.scriv/181.rtfd/TXT.rtf
@@ -0,0 +1,67 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Assets are money that you have, and Liabilities are money that you\
+owe. ``Liabilities'' is just a more inclusive name for Debts.\
+\
+An Asset is typically increased by transferring money from an Income\
+account, such as when you get paid. Here is a typical transaction:\
+\
+@smallexample\
+2004/09/29 My Employer\
+ Assets:Checking $500.00\
+ Income:Salary\
+@end smallexample\
+\
+Money, here, comes from an Income account belonging to ``My\
+Employer'', and is transferred to your checking account. The money is\
+now yours, which makes it an Asset.\
+\
+Liabilities track money owed to others. This can happen when you\
+borrow money to buy something, or if you owe someone money. Here is\
+an example of increasing a MasterCard liability by spending money with\
+it:\
+\
+@smallexample\
+2004/09/30 Restaurant\
+ Expenses:Dining $25.00\
+ Liabilities:MasterCard\
+@end smallexample\
+\
+The Dining account balance now shows $25 spent on Dining, and a\
+corresponding $25 owed on the MasterCard---and therefore shown as\
+$-25.00. The MasterCard liability shows up as negative because it\
+offsets the value of your assets.\
+\
+The combined total of your Assets and Liabilities is your net worth.\
+So to see your current net worth, use this command:\
+\
+@example\
+ledger balance ^assets ^liabilities\
+@end example\
+\
+Relatedly, your Income accounts show up negative, because they\
+transfer money @emph\{from\} an account in order to increase your\
+assets. Your Expenses show up positive because that is where the\
+money went to. The combined total of Income and Expenses is your cash\
+flow. A positive cash flow means you are spending more than you make,\
+since income is always a negative figure. To see your current cash\
+flow, use this command:\
+\
+@example\
+ledger balance ^income ^expenses\
+@end example\
+\
+Another common question to ask of your expenses is: How much do I\
+spend each month on X? Ledger provides a simple way of displaying\
+monthly totals for any account. Here is an example that summarizes\
+your monthly automobile expenses:\
+\
+@example\
+ledger -M register expenses:auto\
+@end example\
+\
+This assumes, of course, that you use account names like\
+@samp\{Expenses:Auto:Gas\} and @samp\{Expenses:Auto:Repair\}.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/182.rtfd/TXT.rtf b/doc/Ledger.scriv/182.rtfd/TXT.rtf
new file mode 100644
index 00000000..cf24e4dc
--- /dev/null
+++ b/doc/Ledger.scriv/182.rtfd/TXT.rtf
@@ -0,0 +1,151 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Sometimes you will want to spend money on behalf of someone else,\
+which will eventually get repaid. Since the money is still ``yours'',\
+it is really an asset. And since the expenditure was for someone\
+else, you don't want it contaminating your Expenses reports. You will\
+need to keep an account for tracking reimbursements.\
+\
+This is fairly easy to do in ledger. When spending the money, spend\
+it @emph\{to\} your Assets:Reimbursements, using a different account for\
+each person or business that you spend money for. For example:\
+\
+@smallexample\
+2004/09/29 Circuit City\
+ Assets:Reimbursements:Company XYZ $100.00\
+ Liabilities:MasterCard\
+@end smallexample\
+\
+This shows $100.00 spent on a MasterCard at Circuit City, with the\
+expense was made on behalf of Company XYZ. Later, when Company XYZ\
+pays the amount back, the money will transfer from that reimbursement\
+account back to a regular asset account:\
+\
+@smallexample\
+2004/09/29 Company XYZ\
+ Assets:Checking $100.00\
+ Assets:Reimbursements:Company XYZ\
+@end smallexample\
+\
+This deposits the money owed from Company XYZ into a checking account,\
+presumably because they paid the amount back with a check.\
+\
+But what to do if you run your own business, and you want to keep\
+track of expenses made on your own behalf, while still tracking\
+everything in a single ledger file? This is more complex, because you\
+need to track two separate things: 1) The fact that the money should\
+be reimbursed to you, and 2) What the expense account was, so that you\
+can later determine where your company is spending its money.\
+\
+This kind of posting is best handled with mirrored postings in\
+two different files, one for your personal accounts, and one for your\
+company accounts. But keeping them in one file involves the same\
+kinds of postings, so those are what is shown here. First, the\
+personal transaction, which shows the need for reimbursement:\
+\
+@smallexample\
+2004/09/29 Circuit City\
+ Assets:Reimbursements:Company XYZ $100.00\
+ Liabilities:MasterCard\
+@end smallexample\
+\
+This is the same as above, except that you own Company XYZ, and are\
+keeping track of its expenses in the same ledger file. This transaction\
+should be immediately followed by an equivalent transaction, which shows the\
+kind of expense, and also notes the fact that $100.00 is now payable\
+to you:\
+\
+@smallexample\
+2004/09/29 Circuit City\
+ Company XYZ:Expenses:Computer:Software $100.00\
+ Company XYZ:Accounts Payable:Your Name\
+@end smallexample\
+\
+This second transaction shows that Company XYZ has just spent $100.00 on\
+software, and that this $100.00 came from Your Name, which must be\
+paid back.\
+\
+These two transactions can also be merged, to make things a little clearer.\
+Note that all amounts must be specified now:\
+\
+@smallexample\
+2004/09/29 Circuit City\
+ Assets:Reimbursements:Company XYZ $100.00\
+ Liabilities:MasterCard $-100.00\
+ Company XYZ:Expenses:Computer:Software $100.00\
+ Company XYZ:Accounts Payable:Your Name $-100.00\
+@end smallexample\
+\
+To ``pay back'' the reimbursement, just reverse the order of\
+everything, except this time drawing the money from a company asset,\
+paying it to accounts payable, and then drawing it again from the\
+reimbursement account, and paying it to your personal asset account.\
+It's easier shown than said:\
+\
+@smallexample\
+2004/10/15 Company XYZ\
+ Assets:Checking $100.00\
+ Assets:Reimbursements:Company XYZ $-100.00\
+ Company XYZ:Accounts Payable:Your Name $100.00\
+ Company XYZ:Assets:Checking $-100.00\
+@end smallexample\
+\
+And now the reimbursements account is paid off, accounts payable is\
+paid off, and $100.00 has been effectively transferred from the\
+company's checking account to your personal checking account. The\
+money simply ``waited''---in both @samp\{Assets:Reimbursements:Company\
+XYZ\}, and @samp\{Company XYZ:Accounts Payable:Your Name\}---until such\
+time as it could be paid off.\
+\
+The value of tracking expenses from both sides like that is that you\
+do not contaminate your personal expense report with expenses made on\
+behalf of others, while at the same time making it possible to\
+generate accurate reports of your company's expenditures. It is more\
+verbose than just paying for things with your personal assets, but it\
+gives you a very accurate information trail.\
+\
+The advantage to keep these doubled transactions together is that they\
+always stay in sync. The advantage to keeping them apart is that it\
+clarifies the transfer's point of view. To keep the postings in\
+separate files, just separate the two transactions that were joined above.\
+For example, for both the expense and the pay-back shown above, the\
+following four transactions would be created. Two in your personal ledger\
+file:\
+\
+@smallexample\
+2004/09/29 Circuit City\
+ Assets:Reimbursements:Company XYZ $100.00\
+ Liabilities:MasterCard $-100.00\
+\
+2004/10/15 Company XYZ\
+ Assets:Checking $100.00\
+ Assets:Reimbursements:Company XYZ $-100.00\
+@end smallexample\
+\
+And two in your company ledger file:\
+\
+@smallexample\
+!account Company XYZ\
+\
+2004/09/29 Circuit City\
+ Expenses:Computer:Software $100.00\
+ Accounts Payable:Your Name $-100.00\
+\
+2004/10/15 Company XYZ\
+ Accounts Payable:Your Name $100.00\
+ Assets:Checking $-100.00\
+\
+!end\
+@end smallexample\
+\
+(Note: The @samp\{!account\} above means that all accounts mentioned in\
+the file are children of that account. In this case it means that all\
+activity in the file relates to Company XYZ).\
+\
+After creating these transactions, you will always know that $100.00 was\
+spent using your MasterCard on behalf of Company XYZ, and that Company\
+XYZ spent the money on computer software and paid it back about two\
+weeks later.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/183.rtfd/TXT.rtf b/doc/Ledger.scriv/183.rtfd/TXT.rtf
new file mode 100644
index 00000000..d64ea52d
--- /dev/null
+++ b/doc/Ledger.scriv/183.rtfd/TXT.rtf
@@ -0,0 +1,15 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 A query such as the following shows all expenses since last\
+October, sorted by total:\
+\
+@example\
+ledger -b "last oct" -s -S T bal ^expenses\
+@end example\
+\
+From left to right the options mean: Show transactions since October, 2003;\
+show all sub-accounts; sort by the absolute value of the total; and\
+report the balance for all expenses.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/184.rtfd/TXT.rtf b/doc/Ledger.scriv/184.rtfd/TXT.rtf
new file mode 100644
index 00000000..1a4c1772
--- /dev/null
+++ b/doc/Ledger.scriv/184.rtfd/TXT.rtf
@@ -0,0 +1,44 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The following query makes it easy to see monthly expenses, with each\
+month's expenses sorted by the amount:\
+\
+@example\
+ledger -M --period-sort t reg ^expenses\
+@end example\
+\
+Now, you might wonder where the money came from to pay for these\
+things. To see that report, add @option\{-r\}, which shows the\
+``related account'' postings:\
+\
+@example\
+ledger -M --period-sort t -r reg ^expenses\
+@end example\
+\
+But maybe this prints too much information. You might just want to\
+see how much you're spending with your MasterCard. That kind of query\
+requires the use of a display predicate, since the postings\
+calculated must match @samp\{^expenses\}, while the postings\
+displayed must match @samp\{mastercard\}. The command would be:\
+\
+@example\
+ledger -M -r -d /mastercard/ reg ^expenses\
+@end example\
+\
+This query says: Report monthly subtotals; report the ``related\
+account'' postings; display only related postings whose\
+account matches @samp\{mastercard\}, and base the calculation on\
+postings matching @samp\{^expenses\}.\
+\
+This works just as well for report the overall total, too:\
+\
+@example\
+ledger -s -r -d /mastercard/ reg ^expenses\
+@end example\
+\
+The @option\{-s\} option subtotals all postings, just as @option\{-M\}\
+subtotaled by the month. The running total in both cases is off,\
+however, since a display expression is being used.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/185.rtfd/TXT.rtf b/doc/Ledger.scriv/185.rtfd/TXT.rtf
new file mode 100644
index 00000000..aca80748
--- /dev/null
+++ b/doc/Ledger.scriv/185.rtfd/TXT.rtf
@@ -0,0 +1,30 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Here are some useful plots:\
+\
+@smallexample\
+report -j -M reg ^expenses # monthly expenses\
+report -J reg checking # checking account balance\
+report -J reg ^income ^expenses # cash flow report\
+\
+# net worth report, ignoring non-$ postings\
+\
+report -J -l "Ua>=@\{\\$0.01@\}" reg ^assets ^liab\
+\
+# net worth report starting last February. the use of a display\
+# predicate (-d) is needed, otherwise the balance will start at\
+# zero, and thus the y-axis will not reflect the true balance\
+\
+report -J -l "Ua>=@\{\\$0.01@\}" -d "d>=[last feb]" reg ^assets ^liab\
+@end smallexample\
+\
+The last report uses both a calculation predicate (@option\{-l\}) and a\
+display predicate (@option\{-d\}). The calculation predicates limits\
+the report to postings whose amount is greater than $1 (which can\
+only happen if the posting amount is in dollars). The display\
+predicate limits the transactions @emph\{displayed\} to just those since last\
+February, even those transactions from before then will be computed as part\
+of the balance.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/186.rtfd/TXT.rtf b/doc/Ledger.scriv/186.rtfd/TXT.rtf
new file mode 100644
index 00000000..3d78f2dd
--- /dev/null
+++ b/doc/Ledger.scriv/186.rtfd/TXT.rtf
@@ -0,0 +1,23 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 If you have @command\{Gnuplot\} installed, you can graph any of the\
+above register reports. The script to do this is included in the\
+ledger distribution, and is named @file\{scripts/report\}. Install\
+@file\{report\} anywhere along your @env\{PATH\}, and then use\
+@command\{report\} instead of @command\{ledger\} when doing a register\
+report. The only thing to keep in mind is that you must specify\
+@option\{-j\} or @option\{-J\} to indicate whether Gnuplot should plot the\
+amount, or the running total. For example, this command plots total\
+monthly expenses made on your MasterCard.\
+\
+@example\
+report -j -M -r -d /mastercard/ reg ^expenses\
+@end example\
+\
+The @command\{report\} script is a very simple Bourne shell script, that\
+passes a set of scripted commands to Gnuplot. Feel free to modify the\
+script to your liking, since you may prefer histograms to line plots,\
+for example.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/188.rtfd/TXT.rtf b/doc/Ledger.scriv/188.rtfd/TXT.rtf
new file mode 100644
index 00000000..be0caf9b
--- /dev/null
+++ b/doc/Ledger.scriv/188.rtfd/TXT.rtf
@@ -0,0 +1,65 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Keeping a budget allows you to pay closer attention to your income and\
+expenses, by reporting how far your actual financial activity is from\
+your expectations.\
+\
+To start keeping a budget, put some period transactions at the top of your\
+ledger file. A period transaction is almost identical to a regular transaction,\
+except that it begins with a tilde and has a period expression in\
+place of a payee. For example:\
+\
+@smallexample\
+~ Monthly\
+ Expenses:Rent $500.00\
+ Expenses:Food $450.00\
+ Expenses:Auto:Gas $120.00\
+ Expenses:Insurance $150.00\
+ Expenses:Phone $125.00\
+ Expenses:Utilities $100.00\
+ Expenses:Movies $50.00\
+ Expenses $200.00 ; all other expenses\
+ Assets\
+\
+~ Yearly\
+ Expenses:Auto:Repair $500.00\
+ Assets\
+@end smallexample\
+\
+These two period transactions give the usual monthly expenses, as well as\
+one typical yearly expense. For help on finding out what your average\
+monthly expense is for any category, use a command like:\
+\
+@example\
+ledger -p "this year" -MAs bal ^expenses\
+@end example\
+\
+The reported totals are the current year's average for each account.\
+\
+Once these period transactions are defined, creating a budget report is as\
+easy as adding @option\{--budget\} to the command-line. For example, a\
+typical monthly expense report would be:\
+\
+@example\
+ledger -M reg ^exp\
+@end example\
+\
+To see the same report balanced against your budget, use:\
+\
+@example\
+ledger --budget -M reg ^exp\
+@end example\
+\
+A budget report includes only those accounts that appear in the\
+budget. To see all expenses balanced against the budget, use\
+@option\{--add-budget\}. You can even see only the unbudgeted expenses\
+using @option\{--unbudgeted\}:\
+\
+@example\
+ledger --unbudgeted -M reg ^exp\
+@end example\
+\
+You can also use these flags with the @command\{balance\} command.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/189.rtfd/TXT.rtf b/doc/Ledger.scriv/189.rtfd/TXT.rtf
new file mode 100644
index 00000000..2a10fad8
--- /dev/null
+++ b/doc/Ledger.scriv/189.rtfd/TXT.rtf
@@ -0,0 +1,24 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Sometimes it's useful to know what your finances will look like in the\
+future, such as determining when an account will reach zero. Ledger\
+makes this easy to do, using the same period transactions as are used for\
+budgeting. An example forecast report can be generated with:\
+\
+@example\
+ledger --forecast "T>@\{\\$-500.00@\}" register ^assets ^liabilities\
+@end example\
+\
+This report continues outputting postings until the running total\
+is greater than $-500.00. A final posting is always output, to\
+show you what the total afterwards would be.\
+\
+Forecasting can also be used with the balance report, but by date\
+only, and not against the running total:\
+\
+@example\
+ledger --forecast "d<[2010]" bal ^assets ^liabilities\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/19.rtfd/TXT.rtf b/doc/Ledger.scriv/19.rtfd/TXT.rtf
new file mode 100644
index 00000000..9d1df1c7
--- /dev/null
+++ b/doc/Ledger.scriv/19.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter Random things} \ No newline at end of file
diff --git a/doc/Ledger.scriv/190.rtfd/TXT.rtf b/doc/Ledger.scriv/190.rtfd/TXT.rtf
new file mode 100644
index 00000000..2d8974f0
--- /dev/null
+++ b/doc/Ledger.scriv/190.rtfd/TXT.rtf
@@ -0,0 +1,93 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Ledger makes no assumptions about the commodities you use; it only\
+requires that you specify a commodity. The commodity may be any\
+non-numeric string that does not contain a period, comma, forward\
+slash or at-sign. It may appear before or after the amount, although\
+it is assumed that symbols appearing before the amount refer to\
+currencies, while non-joined symbols appearing after the amount refer\
+to commodities. Here are some valid currency and commodity\
+specifiers:\
+\
+@example\
+$20.00 ; currency: twenty US dollars\
+40 AAPL ; commodity: 40 shares of Apple stock\
+60 DM ; currency: 60 Deutsch Mark\
+\'a350 ; currency: 50 British pounds\
+50 EUR ; currency: 50 Euros (or use appropriate symbol)\
+@end example\
+\
+Ledger will examine the first use of any commodity to determine how\
+that commodity should be printed on reports. It pays attention to\
+whether the name of commodity was separated from the amount, whether\
+it came before or after, the precision used in specifying the amount,\
+whether thousand marks were used, etc. This is done so that printing\
+the commodity looks the same as the way you use it.\
+\
+An account may contain multiple commodities, in which case it will\
+have separate totals for each. For example, if your brokerage account\
+contains both cash, gold, and several stock quantities, the balance\
+might look like:\
+\
+@smallexample\
+ $200.00\
+100.00 AU\
+ AAPL 40\
+ BORL 100\
+ FEQTX 50 Assets:Brokerage\
+@end smallexample\
+\
+This balance report shows how much of each commodity is in your\
+brokerage account.\
+\
+Sometimes, you will want to know the current street value of your\
+balance, and not the commodity totals. For this to happen, you must\
+specify what the current price is for each commodity. The price can\
+be any commodity, in which case the balance will be computed in terms\
+of that commodity. The usual way to specify prices is with a price\
+history file, which might look like this:\
+\
+@smallexample\
+P 2004/06/21 02:18:01 FEQTX $22.49\
+P 2004/06/21 02:18:01 BORL $6.20\
+P 2004/06/21 02:18:02 AAPL $32.91\
+P 2004/06/21 02:18:02 AU $400.00\
+@end smallexample\
+\
+Specify the price history to use with the @option\{--price-db\} option,\
+with the @option\{-V\} option to report in terms of current market\
+value:\
+\
+@example\
+ledger --price-db prices.db -V balance brokerage\
+@end example\
+\
+The balance for your brokerage account will be reported in US dollars,\
+since the prices database uses that currency.\
+\
+@smallexample\
+$40880.00 Assets:Brokerage\
+@end smallexample\
+\
+You can convert from any commodity to any other commodity. Let's say\
+you had $5000 in your checking account, and for whatever reason you\
+wanted to know many ounces of gold that would buy, in terms of the\
+current price of gold:\
+\
+@example\
+ledger -T "@\{1 AU@\}*(O/P@\{1 AU@\})" balance checking\
+@end example\
+\
+Although the total expression appears complex, it is simply saying\
+that the reported total should be in multiples of AU units, where the\
+quantity is the account total divided by the price of one AU. Without\
+the initial multiplication, the reported total would still use the\
+dollars commodity, since multiplying or dividing amounts always keeps\
+the left value's commodity. The result of this command might be:\
+\
+@smallexample\
+14.01 AU Assets:Checking\
+@end smallexample} \ No newline at end of file
diff --git a/doc/Ledger.scriv/191.rtfd/TXT.rtf b/doc/Ledger.scriv/191.rtfd/TXT.rtf
new file mode 100644
index 00000000..97e61476
--- /dev/null
+++ b/doc/Ledger.scriv/191.rtfd/TXT.rtf
@@ -0,0 +1,23 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Whenever a commodity is purchased using a different commodity (such as\
+a share of common stock using dollars), it establishes a price for\
+that commodity on that day. It is also possible, by recording price\
+details in a ledger file, to specify other prices for commodities at\
+any given time. Such price transactions might look like those below:\
+\
+@smallexample\
+P 2004/06/21 02:17:58 TWCUX $27.76\
+P 2004/06/21 02:17:59 AGTHX $25.41\
+P 2004/06/21 02:18:00 OPTFX $39.31\
+P 2004/06/21 02:18:01 FEQTX $22.49\
+P 2004/06/21 02:18:02 AAPL $32.91\
+@end smallexample\
+\
+By default, ledger will not consider commodity prices when generating\
+its various reports. It will always report balances in terms of the\
+commodity total, rather than the current value of those commodities.\
+To enable pricing reports, use one of the commodity reporting options.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/192.rtfd/TXT.rtf b/doc/Ledger.scriv/192.rtfd/TXT.rtf
new file mode 100644
index 00000000..86dd72e9
--- /dev/null
+++ b/doc/Ledger.scriv/192.rtfd/TXT.rtf
@@ -0,0 +1,55 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Sometimes a commodity has several forms which are all equivalent. An\
+example of this is time. Whether tracked in terms of minutes, hours\
+or days, it should be possible to convert between the various forms.\
+Doing this requires the use of commodity equivalencies.\
+\
+For example, you might have the following two postings, one which\
+transfers an hour of time into a @samp\{Billable\} account, and another\
+which decreases the same account by ten minutes. The resulting report\
+will indicate that fifty minutes remain:\
+\
+@smallexample\
+2005/10/01 Work done for company\
+ Billable:Client 1h\
+ Project:XYZ\
+ \
+2005/10/02 Return ten minutes to the project\
+ Project:XYZ 10m\
+ Billable:Client\
+@end smallexample\
+\
+Reporting the balance for this ledger file produces:\
+\
+@smallexample\
+ 50.0m Billable:Client\
+ -50.0m Project:XYZ\
+@end smallexample\
+\
+This example works because ledger already knows how to handle seconds,\
+minutes and hours, as part of its time tracking support. Defining\
+other equivalencies is simple. The following is an example that\
+creates data equivalencies, helpful for tracking bytes, kilobytes,\
+megabytes, and more:\
+\
+@smallexample\
+C 1.00 Kb = 1024 b\
+C 1.00 Mb = 1024 Kb\
+C 1.00 Gb = 1024 Mb\
+C 1.00 Tb = 1024 Gb\
+@end smallexample\
+\
+Each of these definitions correlates a commodity (such as @samp\{Kb\})\
+and a default precision, with a certain quantity of another commodity.\
+In the above example, kilobytes are reporetd with two decimal places\
+of precision and each kilobyte is equal to 1024 bytes.\
+\
+Equivalency chains can be as long as desired. Whenever a commodity\
+would report as a decimal amount (less than @samp\{1.00\}), the next\
+smallest commodity is used. If a commodity could be reported in terms\
+of a higher commodity without resulting to a partial fraction, then\
+the larger commodity is used.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/193.rtfd/TXT.rtf b/doc/Ledger.scriv/193.rtfd/TXT.rtf
new file mode 100644
index 00000000..adaf020a
--- /dev/null
+++ b/doc/Ledger.scriv/193.rtfd/TXT.rtf
@@ -0,0 +1,39 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Since Ledger's accounts and commodity system is so flexible, you can\
+have accounts that don't really exist, and use commodities that no one\
+else recognizes. For example, let's say you are buying and selling\
+various items in EverQuest, and want to keep track of them using a\
+ledger. Just add items of whatever quantity you wish into your\
+EverQuest account:\
+\
+@smallexample\
+9/29 Get some stuff at the Inn\
+ Places:Black's Tavern -3 Apples\
+ Places:Black's Tavern -5 Steaks\
+ EverQuest:Inventory\
+@end smallexample\
+\
+Now your EverQuest:Inventory has 3 apples and 5 steaks in it. The\
+amounts are negative, because you are taking @emph\{from\} Black's\
+Tavern in order to add to your Inventory account. Note that you don't\
+have to use @samp\{Places:Black's Tavern\} as the source account. You\
+could use @samp\{EverQuest:System\} to represent the fact that you\
+acquired them online. The only purpose for choosing one kind of\
+source account over another is for generate more informative reports\
+later on. The more you know, the better analysis you can perform.\
+\
+If you later sell some of these items to another player, the transaction\
+would look like:\
+\
+@smallexample\
+10/2 Sturm Brightblade\
+ EverQuest:Inventory -2 Steaks\
+ EverQuest:Inventory 15 Gold\
+@end smallexample\
+\
+Now you've turned 2 steaks into 15 gold, courtesy of your customer,\
+Sturm Brightblade.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/194.rtfd/TXT.rtf b/doc/Ledger.scriv/194.rtfd/TXT.rtf
new file mode 100644
index 00000000..00e9d683
--- /dev/null
+++ b/doc/Ledger.scriv/194.rtfd/TXT.rtf
@@ -0,0 +1,40 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The most confusing transaction in any ledger will be your equity account---\
+because starting balances can't come out of nowhere.\
+\
+When you first start your ledger, you will likely already have money\
+in some of your accounts. Let's say there's $100 in your checking\
+account; then add a transaction to your ledger to reflect this amount.\
+Where will money come from? The answer: your equity.\
+\
+@smallexample\
+10/2 Opening Balance\
+ Assets:Checking $100.00\
+ Equity:Opening Balances\
+@end smallexample\
+\
+But what is equity? You may have heard of equity when people talked\
+about house mortgages, as ``the part of the house that you own''.\
+Basically, equity is like the value of something. If you own a car\
+worth $5000, then you have $5000 in equity in that car. In order to\
+turn that car (a commodity) into a cash flow, or a credit to your bank\
+account, you will have to debit the equity by selling it.\
+\
+When you start a ledger, you are probably already worth something.\
+Your net worth is your current equity. By transferring the money in\
+the ledger from your equity to your bank accounts, you are crediting\
+the ledger account based on your prior equity. That is why, when you\
+look at the balance report, you will see a large negative number for\
+Equity that never changes: Because that is what you were worth (what\
+you debited from yourself in order to start the ledger) before the\
+money started moving around. If the total positive value of your\
+assets is greater than the absolute value of your starting equity, it\
+means you are making money.\
+\
+Clear as mud? Keep thinking about it. Until you figure it out, put\
+@samp\{-Equity\} at the end of your balance command, to remove the\
+confusing figure from the total.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/195.rtfd/TXT.rtf b/doc/Ledger.scriv/195.rtfd/TXT.rtf
new file mode 100644
index 00000000..66781398
--- /dev/null
+++ b/doc/Ledger.scriv/195.rtfd/TXT.rtf
@@ -0,0 +1,32 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Something that stops many people from keeping a ledger at all is the\
+insanity of tracking small cash expenses. They rarely generate a\
+receipt, and there are often a lot of small postings, rather than\
+a few large ones, as with checks.\
+\
+One solution is: don't bother. Move your spending to a debit card,\
+but in general ignore cash. Once you withdraw it from the ATM, mark\
+it as already spent to an @samp\{Expenses:Cash\} category:\
+\
+@smallexample\
+2004/03/15 ATM\
+ Expenses:Cash $100.00\
+ Assets:Checking\
+@end smallexample\
+\
+If at some point you make a large cash expense that you want to track,\
+just ``move'' the amount of the expense from @samp\{Expenses:Cash\} into\
+the target account:\
+\
+@smallexample\
+2004/03/20 Somebody\
+ Expenses:Food $65.00\
+ Expenses:Cash\
+@end smallexample\
+\
+This way, you can still track large cash expenses, while ignoring all\
+of the smaller ones.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/196.rtfd/TXT.rtf b/doc/Ledger.scriv/196.rtfd/TXT.rtf
new file mode 100644
index 00000000..cf24b656
--- /dev/null
+++ b/doc/Ledger.scriv/196.rtfd/TXT.rtf
@@ -0,0 +1,137 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 There are situations when the accounts you're tracking are different\
+between your clients and the financial institutions where money is\
+kept. An example of this is working as the treasurer for a religious\
+institution. From the secular point of view, you might be working\
+with three different accounts:\
+\
+@itemize\
+@item Checking\
+@item Savings\
+@item Credit Card\
+@end itemize\
+\
+From a religious point of view, the community expects to divide its\
+resources into multiple ``funds'', from which it makes purchases or\
+reserves resources for later:\
+\
+@itemize\
+@item School fund\
+@item Building fund\
+@item Community fund\
+@end itemize\
+\
+The problem with this kind of setup is that when you spend money, it\
+comes from two or more places at once: the account and the fund. And\
+yet, the correlation of amounts between funds and accounts is rarely\
+one-to-one. What if the school fund has @samp\{$500.00\}, but\
+@samp\{$400.00\} of that comes from Checking, and @samp\{$100.00\} from\
+Savings?\
+\
+Traditional finance packages require that the money reside in only one\
+place. But there are really two ``views'' of the data: from the\
+account point of view and from the fund point of view -- yet both sets\
+should reflect the same overall expenses and cash flow. It's simply\
+where the money resides that differs.\
+\
+This situation can be handled one of two ways. The first is using\
+virtual postings to represent the fact that money is moving to and\
+from two kind of accounts at the same time:\
+\
+@smallexample\
+2004/03/20 Contributions\
+ Assets:Checking $500.00\
+ Income:Donations\
+\
+2004/03/25 Distribution of donations\
+ [Funds:School] $300.00\
+ [Funds:Building] $200.00\
+ [Assets:Checking] $-500.00\
+@end smallexample\
+\
+The use of square brackets in the second transaction ensures that the\
+virtual postings balance to zero. Now money can be spent directly\
+from a fund at the same time as money is drawn from a physical\
+account:\
+\
+@smallexample\
+2004/03/25 Payment for books (paid from Checking)\
+ Expenses:Books $100.00\
+ Assets:Checking $-100.00\
+ (Funds:School) $-100.00\
+@end smallexample\
+\
+When reports are generated, by default they'll appear in terms of the\
+funds. In this case, you will likely want to mask out your\
+@samp\{Assets\} account, because otherwise the balance won't make much\
+sense:\
+\
+@example\
+ledger bal -^Assets\
+@end example\
+\
+If the @option\{--real\} option is used, the report will be in terms of\
+the real accounts:\
+\
+@example\
+ledger --real bal\
+@end example\
+\
+If more asset accounts are needed as the source of a posting, just\
+list them as you would normally, for example:\
+\
+@smallexample\
+2004/03/25 Payment for books (paid from Checking)\
+ Expenses:Books $100.00\
+ Assets:Checking $-50.00\
+ Liabilities:Credit Card $-50.00\
+ (Funds:School) $-100.00\
+@end smallexample\
+\
+The second way of tracking funds is to use transaction codes. In this\
+respect the codes become like virtual accounts that embrace the entire\
+set of postings. Basically, we are associating a transaction with a\
+fund by setting its code. Here are two transactions that desposit money\
+into, and spend money from, the @samp\{Funds:School\} fund:\
+\
+@smallexample\
+2004/03/25 (Funds:School) Donations\
+ Assets:Checking $100.00\
+ Income:Donations\
+\
+2004/04/25 (Funds:School) Payment for books\
+ Expenses:Books $50.00\
+ Assets:Checking\
+@end smallexample\
+\
+Note how the accounts now relate only to the real accounts, and any\
+balance or registers reports will reflect this. That the transactions\
+relate to a particular fund is kept only in the code.\
+\
+How does this become a fund report? By using the\
+@option\{--code-as-payee\} option, you can generate a register report\
+where the payee for each posting shows the code. Alone, this is\
+not terribly interesting; but when combined with the\
+@option\{--by-payee\} option, you will now see account subtotals for any\
+postings related to a specific fund. So, to see the current\
+monetary balances of all funds, the command would be:\
+\
+@smallexample\
+ledger --code-as-payee -P reg ^Assets\
+@end smallexample\
+\
+Or to see a particular funds expenses, the @samp\{School\} fund in this\
+case:\
+\
+@smallexample\
+ledger --code-as-payee -P reg ^Expenses -- School\
+@end smallexample\
+\
+Both approaches yield different kinds of flexibility, depending on how\
+you prefer to think of your funds: as virtual accounts, or as tags\
+associated with particular transactions. Your own tastes will decide which\
+is best for your situation.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/197.rtfd/TXT.rtf b/doc/Ledger.scriv/197.rtfd/TXT.rtf
new file mode 100644
index 00000000..34552f70
--- /dev/null
+++ b/doc/Ledger.scriv/197.rtfd/TXT.rtf
@@ -0,0 +1,61 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 After a while, your ledger can get to be pretty large. While this\
+will not slow down the ledger program much---it's designed to process\
+ledger files very quickly---things can start to feel ``messy''; and\
+it's a universal complaint that when finances feel messy, people avoid\
+them.\
+\
+Thus, archiving the data from previous years into their own files can\
+offer a sense of completion, and freedom from the past. But how to\
+best accomplish this with the ledger program? There are two commands\
+that make it very simple: @command\{print\}, and @command\{equity\}.\
+\
+Let's take an example file, with data ranging from year 2000 until\
+2004. We want to archive years 2000 and 2001 to their own file,\
+leaving just 2003 and 2004 in the current file. So, use\
+@command\{print\} to output all the earlier transactions to a file called\
+@file\{ledger-old.dat\}:\
+\
+@smallexample\
+ledger -f ledger.dat -b 2000 -e 2001 print > ledger-old.dat\
+@end smallexample\
+\
+To delete older data from the current ledger file, use @command\{print\}\
+again, this time specifying year 2002 as the starting date:\
+\
+@example\
+ledger -f ledger.dat -b 2002 print > x\
+mv x ledger.dat\
+@end example\
+\
+However, now the current file contains @emph\{only\} postings from\
+2002 onward, which will not yield accurate present-day balances,\
+because the net income from previous years is no longer being tallied.\
+To compensate for this, we must append an equity report for the old\
+ledger at the beginning of the new one:\
+\
+@example\
+ledger -f ledger-old.dat equity > equity.dat\
+cat equity.dat ledger.dat > x\
+mv x ledger.dat\
+rm equity.dat\
+@end example\
+\
+Now the balances reported from @file\{ledger.dat\} are identical to what\
+they were before the data was split.\
+\
+How often should you split your ledger? You never need to, if you\
+don't want to. Even eighty years of data will not slow down ledger\
+much---and that's just using present day hardware! Or, you can keep\
+the previous and current year in one file, and each year before that\
+in its own file. It's really up to you, and how you want to organize\
+your finances. For those who also keep an accurate paper trail, it\
+might be useful to archive the older years to their own files, then\
+burn those files to a CD to keep with the paper records---along with\
+any electronic statements received during the year. In the arena of\
+organization, just keep in mind this maxim: Do whatever keeps you\
+doing it.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/198.rtfd/TXT.rtf b/doc/Ledger.scriv/198.rtfd/TXT.rtf
new file mode 100644
index 00000000..5916b022
--- /dev/null
+++ b/doc/Ledger.scriv/198.rtfd/TXT.rtf
@@ -0,0 +1,42 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 A virtual posting is when you, in your mind, see money as moving\
+to a certain place, when in reality that money has not moved at all.\
+There are several scenarios in which this type of tracking comes in\
+handy, and each of them will be discussed in detail.\
+\
+To enter a virtual posting, surround the account name in\
+parentheses. This form of usage does not need to balance. However,\
+if you want to ensure the virtual posting balances with other\
+virtual postings in the same transaction, use square brackets. For\
+example:\
+\
+@smallexample\
+10/2 Paycheck\
+ Assets:Checking $1000.00\
+ Income:Salary $-1000.00\
+ (Debt:Alimony) $200.00\
+@end smallexample\
+\
+In this example, after receiving a paycheck an alimony debt is\
+increased---even though no money has moved around yet.\
+\
+@smallexample\
+10/2 Paycheck\
+ Assets:Checking $1000.00\
+ Income:Salary $-1000.00\
+ [Savings:Trip] $200.00\
+ [Assets:Checking] $-200.00\
+@end smallexample\
+\
+In this example, $200 has been deducted from checking toward savings\
+for a trip. It will appear as though the money has been moved from\
+the account into @samp\{Savings:Trip\}, although no money has actually\
+moved anywhere.\
+\
+When balances are displayed, virtual postings will be factored in.\
+To view balances without any virtual balances factored in, using the\
+@option\{-R\} flag, for ``reality''.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/199.rtfd/TXT.rtf b/doc/Ledger.scriv/199.rtfd/TXT.rtf
new file mode 100644
index 00000000..8a92a803
--- /dev/null
+++ b/doc/Ledger.scriv/199.rtfd/TXT.rtf
@@ -0,0 +1,79 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 As a Bah\'e1'\'ed, I need to compute Huq\'faqu'll\'e1h whenever I acquire assets.\
+It is similar to tithing for Jews and Christians, or to Zak\'e1t for\
+Muslims. The epost details of computing Huq\'faqu'll\'e1h are somewhat\
+complex, but if you have further interest, please consult the Web.\
+\
+Ledger makes this otherwise difficult law very easy. Just set up an\
+automated posting at the top of your ledger file:\
+\
+@smallexample\
+; This automated transaction will compute Huq\'faqu'll\'e1h based on this\
+; journal's postings. Any that match will affect the\
+; Liabilities:Huququ'llah account by 19% of the value of that\
+; posting.\
+\
+= /^(?:Income:|Expenses:(?:Business|Rent$|Furnishings|Taxes|Insurance))/\
+ (Liabilities:Huququ'llah) 0.19\
+@end smallexample\
+\
+This automated posting works by looking at each posting in the\
+ledger file. If any match the given value expression, 19% of the\
+posting's value is applied to the @samp\{Liabilities:Huququ'llah\}\
+account. So, if $1000 is earned from @samp\{Income:Salary\}, $190 is\
+added to @samp\{Liabilities:Huq\'faqu'll\'e1h\}; if $1000 is spent on Rent,\
+$190 is subtracted. The ultimate balance of Huq\'faqu'll\'e1h reflects how\
+much is owed in order to fulfill one's obligation to Huq\'faqu'll\'e1h.\
+When ready to pay, just write a check to cover the amount shown in\
+@samp\{Liabilities:Huququ'llah\}. That transaction would look like:\
+\
+@smallexample\
+2003/01/01 (101) Baha'i Huq\'faqu'll\'e1h Trust\
+ Liabilities:Huququ'llah $1,000.00\
+ Assets:Checking\
+@end smallexample\
+\
+That's it. To see how much Huq\'faq is currently owed based on your\
+ledger transactions, use:\
+\
+@example\
+ledger balance Liabilities:Huquq\
+@end example\
+\
+This works fine, but omits one aspect of the law: that Huquq is only\
+due once the liability exceeds the value of 19 mithq\'e1ls of gold (which\
+is roughly 2.22 ounces). So what we want is for the liability to\
+appear in the balance report only when it exceeds the present day\
+value of 2.22 ounces of gold. This can be accomplished using the\
+command:\
+\
+@smallexample\
+ledger -Q -t "/Liab.*Huquq/?(a/P@\{2.22 AU@\}<=@\{-1.0@\}&a):a" -s bal liab\
+@end smallexample\
+\
+With this command, the current price for gold is downloaded, and the\
+Huq\'faqu'll\'e1h is reported only if its value exceeds that of 2.22 ounces\
+of gold. If you wish the liability to be reflected in the parent\
+subtotal either way, use this instead:\
+\
+@smallexample\
+ledger -Q -T "/Liab.*Huquq/?(O/P@\{2.22 AU@\}<=@\{-1.0@\}&O):O" -s bal liab\
+@end smallexample\
+\
+In some cases, you may wish to refer to the account of whichever\
+posting matched your automated transaction's value expression. To do\
+this, use the special account name @samp\{$account\}:\
+\
+@smallexample\
+= /^Some:Long:Account:Name/\
+ [$account] -0.10\
+ [Savings] 0.10\
+@end smallexample\
+\
+This example causes 10% of the matching account's total to be deferred\
+to the @samp\{Savings\} account---as a balanced virtual posting,\
+which may be excluded from reports by using @option\{--real\}.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/20.rtfd/TXT.rtf b/doc/Ledger.scriv/20.rtfd/TXT.rtf
new file mode 100644
index 00000000..4d44556b
--- /dev/null
+++ b/doc/Ledger.scriv/20.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter Anatomy of a journal file} \ No newline at end of file
diff --git a/doc/Ledger.scriv/200.rtfd/TXT.rtf b/doc/Ledger.scriv/200.rtfd/TXT.rtf
new file mode 100644
index 00000000..10d8c9f1
--- /dev/null
+++ b/doc/Ledger.scriv/200.rtfd/TXT.rtf
@@ -0,0 +1,104 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 In the Ledger tarball is an Emacs module, @file\{ledger.el\}. This\
+module makes the process of keeping a text ledger much easier for\
+Emacs users. I recommend putting this at the top of your ledger file:\
+\
+@example\
+; -*-ledger-*-\
+@end example\
+\
+And this in your @file\{.emacs\} file, after copying @file\{ledger.el\} to\
+your @file\{site-lisp\} directory:\
+\
+@example\
+(load "ledger")\
+@end example\
+\
+Now when you edit your ledger file, it will be in\
+@command\{ledger-mode\}. @command\{ledger-mode\} adds these commands:\
+\
+@table @strong\
+@item C-c C-a\
+For quickly adding new transactions based on the form of older ones (see\
+previous section).\
+\
+@item C-c C-c\
+Toggles the ``cleared'' flag of the posting under point.\
+\
+@item C-c C-d\
+Delete the transaction under point.\
+\
+@item C-c C-r\
+Reconciles an account by displaying the postings in another\
+buffer, where simply hitting the spacebar will toggle the pending flag\
+of the posting in the ledger. Once all the appropriate\
+postings have been marked, press C-c C-c in the reconcile buffer\
+to ``commit'' the reconciliation, which will mark all of the transactions\
+as cleared, and display the new cleared balance in the minibuffer.\
+\
+@item C-c C-m\
+Set the default month for new transactions added with C-c C-a. This is\
+handy if you have a large number of postings to enter from a\
+previous month.\
+\
+@item C-c C-y\
+Set the default year for new transactions added with C-c C-a. This is\
+handy if you have a large number of postings to enter from a\
+previous year.\
+@end table\
+\
+Once you enter the reconcile buffer, there are several key commands\
+available:\
+\
+@table @strong\
+@item RET\
+Visit the ledger file transaction corresponding to the reconcile transaction.\
+\
+@item C-c C-c\
+Commit the reconcialation. This marks all of the marked postings\
+as ``cleared'', saves the ledger file, and then displays the new\
+cleared balance.\
+\
+@item C-l\
+Refresh the reconcile buffer by re-reading postings from the\
+ledger data file.\
+\
+@item SPC\
+Toggle the posting under point as cleared.\
+\
+@item a\
+Add a new transaction to the ledger data file, and refresh the reconcile\
+buffer to include its postings (if the transaction is added to the same\
+account as the one being reconciled).\
+\
+@item d\
+Delete the transaction related to the posting under point. Note: This\
+may result in multiple postings being deleted.\
+\
+@item n\
+Move to the next line.\
+\
+@item p\
+Move to the previous line.\
+\
+@item C-c C-r\
+@item r\
+Attempt to auto-reconcile the postings to the entered balance. If\
+it can do so, it will mark all those postings as pending that\
+would yield the specified balance.\
+\
+@item C-x C-s\
+@item s\
+Save the ledger data file, and show the current cleared balance for\
+the account being reconciled.\
+\
+@item q\
+Quit the reconcile buffer.\
+@end table\
+\
+There is also an @command\{emacs\} command which can be used to output\
+reports in a format directly @code\{read\}-able from Emacs Lisp.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/201.rtfd/TXT.rtf b/doc/Ledger.scriv/201.rtfd/TXT.rtf
new file mode 100644
index 00000000..30dfdd60
--- /dev/null
+++ b/doc/Ledger.scriv/201.rtfd/TXT.rtf
@@ -0,0 +1,18 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The Ledger tool is fast and simple, but it offers no custom method for\
+actually editing the ledger. It assumes you know how to use a text\
+editor, and like doing so. There is, at least, an Emacs mode that\
+makes editing Ledger's data files much easier.\
+\
+You are also free to use GnuCash to maintain your ledger, and the\
+Ledger program for querying and reporting on the contents of that\
+ledger. It takes a little longer to parse the XML data format that\
+GnuCash uses, but the end result is identical.\
+\
+Then again, why would anyone use a Gnome-centric, multi-megabyte\
+behemoth to edit their data, and only a one megabyte binary to query\
+it?} \ No newline at end of file
diff --git a/doc/Ledger.scriv/202.rtfd/TXT.rtf b/doc/Ledger.scriv/202.rtfd/TXT.rtf
new file mode 100644
index 00000000..d5ac2a48
--- /dev/null
+++ b/doc/Ledger.scriv/202.rtfd/TXT.rtf
@@ -0,0 +1,92 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The timeclock tool makes it easy to track time events, like clocking\
+into and out of a particular job. These events accumulate in a\
+timelog file.\
+\
+Each in/out event may have an optional description. If the ``in''\
+description is a ledger account name, these in/out pairs may be viewed\
+as virtual postings, adding time commodities (hours) to that\
+account.\
+\
+For example, the command-line version of the timeclock tool could be\
+used to begin a timelog file like:\
+\
+@example\
+export TIMELOG=$HOME/.timelog\
+ti ClientOne category\
+sleep 10\
+to waited for ten seconds\
+@end example\
+\
+The @file\{.timelog\} file now contains:\
+\
+@smallexample\
+i 2004/10/06 15:21:00 ClientOne category\
+o 2004/10/06 15:21:10 waited for ten seconds\
+@end smallexample\
+\
+Ledger parses this directly, as if it had seen the following transaction:\
+\
+@smallexample\
+2004/10/06 category\
+ (ClientOne) 10s\
+@end smallexample\
+\
+In other words, the timelog event pair is seen as adding 0.00277h (ten\
+seconds) worth of time to the @samp\{ClientOne\} account. This would be\
+considered billable time, which later could be invoiced and credited\
+to accounts receivable:\
+\
+@smallexample\
+2004/11/01 (INV#1) ClientOne, Inc.\
+ Receivable:ClientOne $0.10\
+ ClientOne -0.00277h @@ $35.00\
+@end smallexample\
+\
+The above posting converts the clocked time into an invoice for\
+the time spent, at an hourly rate of $35. Once the invoice is paid,\
+the money is deposited from the receivable account into a checking\
+account:\
+\
+@smallexample\
+2004/12/01 ClientOne, Inc.\
+ Assets:Checking $0.10\
+ Receivable:ClientOne\
+@end smallexample\
+\
+And now the time spent has been turned into hard cash in the checking\
+account.\
+\
+The advantage to using timeclock and invoicing to bill time is that\
+you will always know, by looking at the balance report, epostly how\
+much unbilled and unpaid time you've spent working for any particular\
+client.\
+\
+I like to @samp\{!include\} my timelog at the top of my company's\
+accounting ledger, with the attached prefix @samp\{Billable\}:\
+\
+@smallexample\
+; -*-ledger-*-\
+\
+; This is the ledger file for my company. But first, include the\
+; timelog data, entering all of the time events within the umbrella\
+; account "Billable".\
+\
+!account Billable\
+!include /home/johnw/.timelog\
+!end\
+\
+; Here follows this fiscal year's postings for the company.\
+\
+2004/11/01 (INV#1) ClientOne, Inc.\
+ Receivable:ClientOne $0.10\
+ Billable:ClientOne -0.00277h @@ $35.00\
+\
+2004/12/01 ClientOne, Inc.\
+ Assets:Checking $0.10\
+ Receivable:ClientOne\
+@end smallexample} \ No newline at end of file
diff --git a/doc/Ledger.scriv/203.rtfd/TXT.rtf b/doc/Ledger.scriv/203.rtfd/TXT.rtf
new file mode 100644
index 00000000..50220a9a
--- /dev/null
+++ b/doc/Ledger.scriv/203.rtfd/TXT.rtf
@@ -0,0 +1,152 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 By default, Ledger uses a human-readable data format, and displays its\
+reports in a manner meant to be read on screen. For the purpose of\
+writing tools which use Ledger, however, it is possible to read and\
+display data using XML. This section documents that format.\
+\
+The general format used for Ledger data is:\
+\
+@smallexample\
+<?xml version="1.0"?>\
+<ledger>\
+ <xact>...</xact>\
+ <xact>...</xact>\
+ <xact>...</xact>...\
+</ledger>\
+@end smallexample\
+\
+The data stream is enclosed in a @samp\{ledger\} tag, which contains a\
+series of one or more transactions. Each @samp\{xact\} describes the transaction\
+and contains a series of one or more postings:\
+\
+@smallexample\
+<xact>\
+ <en:date>2004/03/01</en:date>\
+ <en:cleared/>\
+ <en:code>100</en:code>\
+ <en:payee>John Wiegley</en:payee>\
+ <en:postings>\
+ <posting>...</posting>\
+ <posting>...</posting>\
+ <posting>...</posting>...\
+ </en:postings>\
+</xact>\
+@end smallexample\
+\
+The date format for @samp\{en:date\} is always @samp\{YYYY/MM/DD\}. The\
+@samp\{en:cleared\} tag is optional, and indicates whether the\
+posting has been cleared or not. There is also an\
+@samp\{en:pending\} tag, for marking pending postings. The\
+@samp\{en:code\} and @samp\{en:payee\} tags both contain whatever text the\
+user wishes.\
+\
+After the initial transaction data, there must follow a set of postings\
+marked with @samp\{en:postings\}. Typically these postings will\
+all balance each other, but if not they will be automatically balanced\
+into an account named @samp\{<Unknown>\}.\
+\
+Within the @samp\{en:postings\} tag is a series of one or more\
+@samp\{posting\}'s, which have the following form:\
+\
+@smallexample\
+<posting>\
+ <tr:account>Expenses:Computer:Hardware</tr:account>\
+ <tr:amount>\
+ <value type="amount">\
+ <amount>\
+ <commodity flags="PT">$</commodity>\
+ <quantity>90.00</quantity>\
+ </amount>\
+ </value>\
+ </tr:amount>\
+</posting>\
+@end smallexample\
+\
+This is a basic posting. It may also be begin with\
+@samp\{tr:virtual\} and/or @samp\{tr:generated\} tags, to indicate virtual\
+and auto-generated postings. Then follows the @samp\{tr:account\}\
+tag, which contains the full name of the account the posting is\
+related to. Colons separate parent from child in an account name.\
+\
+Lastly follows the amount of the posting, indicated by\
+@samp\{tr:amount\}. Within this tag is a @samp\{value\} tag, of which\
+there are four different kinds, each with its own format:\
+\
+@enumerate\
+@item boolean\
+@item integer\
+@item amount\
+@item balance\
+@end enumerate\
+\
+The format of a boolean value is @samp\{true\} or @samp\{false\}\
+surrounded by a @samp\{boolean\} tag, for example:\
+\
+@smallexample\
+<boolean>true</boolean>\
+@end smallexample\
+\
+The format of an integer value is the numerical value surrounded by an\
+@samp\{integer\} tag, for example:\
+\
+@smallexample\
+<integer>12036</integer>\
+@end smallexample\
+\
+The format of an amount contains two members, the commodity and the\
+quantity. The commodity can have a set of flags that indicate how to\
+display it. The meaning of the flags (all of which are optional) are:\
+\
+@table @strong\
+@item P\
+The commodity is prefixed to the value.\
+@item S\
+The commodity is separated from the value by a space.\
+@item T\
+Thousands markers are used to display the amount.\
+@item E\
+The format of the amount is European, with period used as a thousands\
+marker, and comma used as the decimal point.\
+@end table\
+\
+The actual quantity for an amount is an integer of arbitrary size.\
+Ledger uses the GNU multi-precision math library to handle such\
+values. The XML format assumes the reader to be equally capable.\
+Here is an example amount:\
+\
+@smallexample\
+<value type="amount">\
+ <amount>\
+ <commodity flags="PT">$</commodity>\
+ <quantity>90.00</quantity>\
+ </amount>\
+</value>\
+@end smallexample\
+\
+Lastly, a balance value contains a series of amounts, each with a\
+different commodity. Unlike the name, such a value does need to\
+balance. It is called a balance because it sums several amounts. For\
+example:\
+\
+@smallexample\
+<value type="balance">\
+ <balance>\
+ <amount>\
+ <commodity flags="PT">$</commodity>\
+ <quantity>90.00</quantity>\
+ </amount>\
+ <amount>\
+ <commodity flags="TE">DM</commodity>\
+ <quantity>200.00</quantity>\
+ </amount>\
+ </balance>\
+</value>\
+@end smallexample\
+\
+That is the extent of the XML data format used by Ledger. It will\
+output such data if the @command\{xml\} command is used, and can read\
+the same data.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/204.rtfd/TXT.rtf b/doc/Ledger.scriv/204.rtfd/TXT.rtf
new file mode 100644
index 00000000..5b88f311
--- /dev/null
+++ b/doc/Ledger.scriv/204.rtfd/TXT.rtf
@@ -0,0 +1,41 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Whenever a commodity is exchanged for another in a posting, one of the\
+two is considered @emph\{primary\}, and the other secondary.\
+Primariness of a commodity is remembered, since the @option\{--market\}\
+option only renders balances into secondary commodities, never\
+primaries. To render primaries, use the @option\{--exchange=COMMODITY\}\
+option.\
+\
+In all of the following examples, the P commodity is considered primary\
+and the S is secondary (the P at the beginning of the line indicates a\
+price-setting directive):\
+\
+@smallexample\
+2009/01/01 Sample 1a\
+ Assets:Brokerage:Stocks 100 S\
+ Assets:Brokerage:Cash -100 P\
+\
+P 2009/01/15 00:00:00 S 2 P\
+\
+2009/02/01 Sample 2a\
+ Assets:Brokerage:Stocks 100 S @ 1 P\
+ Assets:Brokerage:Cash\
+\
+P 2009/02/01 00:00:00 S 4 P\
+\
+2009/03/01 Sample 3a\
+ Assets:Brokerage:Stocks 100 S @@ 100 P\
+ Assets:Brokerage:Cash\
+\
+P 2009/03/01 00:00:00 S 8 P\
+\
+2009/04/01 Sample 4a\
+ Assets:Brokerage:Cash 100 P\
+ Assets:Brokerage:Stocks -100 S @\{1 P@\}\
+\
+P 2009/04/01 00:00:00 S 16 P\
+@end smallexample} \ No newline at end of file
diff --git a/doc/Ledger.scriv/205.rtfd/TXT.rtf b/doc/Ledger.scriv/205.rtfd/TXT.rtf
new file mode 100644
index 00000000..50195aad
--- /dev/null
+++ b/doc/Ledger.scriv/205.rtfd/TXT.rtf
@@ -0,0 +1,39 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Everything begins with a journal file---the anatomy of which is covered\
+in detail in chapter one. To review: a @emph\{journal\} contains one or\
+more @emph\{transactions\}, each of which refers to two or more\
+@emph\{postings\}. A @emph\{posting\} specifies that a given\
+@emph\{amount\} is added to, or subtracted from, an @emph\{account\}.\
+(@emph\{Accounts\} may be nested hierarchically by separating the elements\
+using a colon). Lastly, an @emph\{amount\} is a figure representing a\
+given @emph\{quantity\} of a @emph\{commodity\}. Here follows a review of\
+these terms, which are all used extensively throughout this chapter:\
+\
+@table @emph\
+@item journal\
+A journal is a data file containing a series of transactions.\
+\
+@item transaction\
+a transaction relates a group of two or more postings, with the absolute\
+constraint that the total sum of a transaction's postings must equal\
+zero. That is, every transaction in a journal must @emph\{balance\} to zero.\
+\
+@item posting\
+Postings record how commodities are moved between accounts. If you\
+spent money on a movie ticket, for example, such a transaction would have two\
+postings: One to show how the money was taken from your wallet, and\
+another to show how it was applied to your movie expenses.\
+\
+@item account\
+An account \
+\
+@item amount\
+\
+@item quantity\
+\
+@item commodity\
+@end table} \ No newline at end of file
diff --git a/doc/Ledger.scriv/207.rtfd/TXT.rtf b/doc/Ledger.scriv/207.rtfd/TXT.rtf
new file mode 100644
index 00000000..957c3df1
--- /dev/null
+++ b/doc/Ledger.scriv/207.rtfd/TXT.rtf
@@ -0,0 +1,18 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Once you have a journal file representing a recent history of your\
+finances, the next step is to generate reports in order to give richer\
+meaning to this data. For example: Where do you spend your money? Do\
+you have enough to cover upcoming expenses? Are you creating or losing\
+net worth? Are your investment performing well? All of these questions\
+can be answered easily with Ledger---if you know how to ask them.\
+\
+Preparing complex reports is not a simple task, but neither is it a\
+difficult one. All that's required is a proper understanding of how\
+Ledger views your data, and how it prepares it for reporting.\
+\
+After Ledger reads a journal file, it creates an in-memory\
+representation reflecting the order and composition of those transactions.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/21.rtfd/TXT.rtf b/doc/Ledger.scriv/21.rtfd/TXT.rtf
new file mode 100644
index 00000000..e6bbfb11
--- /dev/null
+++ b/doc/Ledger.scriv/21.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter Example accounting practices} \ No newline at end of file
diff --git a/doc/Ledger.scriv/211.rtfd/TXT.rtf b/doc/Ledger.scriv/211.rtfd/TXT.rtf
new file mode 100644
index 00000000..95a9e710
--- /dev/null
+++ b/doc/Ledger.scriv/211.rtfd/TXT.rtf
@@ -0,0 +1,29 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The following sections discuss how Ledger is architected, from the\
+ground up, and will show how to use the various parts of the Ledger\
+library from your own scripts. Ledger essentially follows five steps in\
+reporting data to the user:\
+\
+@enumerate\
+@item Parse journal file into an internal representation\
+@item Perform any implied math within the journal file\
+@item ``Face'' this internal representation as a virtual document\
+@item Apply a series of transforms to the virtual document\
+@item Display the virtual document using a formatting command\
+@end enumerate\
+\
+The calculations in step two are specified by the user, such as when a\
+posting's value might contain mathematical operators. The\
+calculations in step four are implied in the transformations, for\
+example when the @option\{--average\} option is used.\
+\
+At the core, however, Ledger is basically a sophisticated calculator\
+with special knowledge about commoditized values. It knows what you\
+mean if you add ten dollars to twenty euros, and later ask for the\
+balance of that particular account. So it follows that first we must\
+discuss how Ledger deals with math, and from there move on to describing\
+how the steps above are achieved.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/213.rtfd/TXT.rtf b/doc/Ledger.scriv/213.rtfd/TXT.rtf
new file mode 100644
index 00000000..ae45e0a7
--- /dev/null
+++ b/doc/Ledger.scriv/213.rtfd/TXT.rtf
@@ -0,0 +1,22 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The most fundamental type in Ledger is the amount, which may or may\
+not have a commodity attached to it. First, we'll deal with the bare\
+case, just to show how the amount type works. In C++, most all of\
+Ledger's internal types end in @code\{_t\}; in Python, the same type\
+name is used, but the @code\{_t\} suffix is dropped. Examples of usage\
+in both languages will be presented throughout.\
+\
+amount_t\
+commodity_t\
+updater_t\
+datetime_t\
+balance_t\
+balance_pair_t\
+value_t\
+valexpr_t\
+format_t\
+mask_t} \ No newline at end of file
diff --git a/doc/Ledger.scriv/214.rtfd/TXT.rtf b/doc/Ledger.scriv/214.rtfd/TXT.rtf
new file mode 100644
index 00000000..8f62d437
--- /dev/null
+++ b/doc/Ledger.scriv/214.rtfd/TXT.rtf
@@ -0,0 +1,10 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 journal_t\
+account_t\
+xact_t\
+post_t\
+parser_t} \ No newline at end of file
diff --git a/doc/Ledger.scriv/218.rtfd/TXT.rtf b/doc/Ledger.scriv/218.rtfd/TXT.rtf
new file mode 100644
index 00000000..d606ec9f
--- /dev/null
+++ b/doc/Ledger.scriv/218.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @bye} \ No newline at end of file
diff --git a/doc/Ledger.scriv/219.rtfd/TXT.rtf b/doc/Ledger.scriv/219.rtfd/TXT.rtf
new file mode 100644
index 00000000..d5d5fbe5
--- /dev/null
+++ b/doc/Ledger.scriv/219.rtfd/TXT.rtf
@@ -0,0 +1,8 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Ledger is, at heart, just a sophisticated calculator. In addition to summing values within \'93accounts\'94, it guarantees that every transaction balances to zero to confirm these values are correctly transferred between accounts.\
+\
+In addition to using this calculator from the command-line to generate reports, you may also access it from the Python scripting language, in order to manipulate the figures however you wish. The following chapter presents the ideas you will need to know to accomplish this, as well as many typical idioms used by the Ledger module.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/22.rtfd/TXT.rtf b/doc/Ledger.scriv/22.rtfd/TXT.rtf
new file mode 100644
index 00000000..b9b6facb
--- /dev/null
+++ b/doc/Ledger.scriv/22.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter Generating useful reports} \ No newline at end of file
diff --git a/doc/Ledger.scriv/220.rtfd/TXT.rtf b/doc/Ledger.scriv/220.rtfd/TXT.rtf
new file mode 100644
index 00000000..067472cb
--- /dev/null
+++ b/doc/Ledger.scriv/220.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Creating a session} \ No newline at end of file
diff --git a/doc/Ledger.scriv/221.rtfd/TXT.rtf b/doc/Ledger.scriv/221.rtfd/TXT.rtf
new file mode 100644
index 00000000..6e69ff52
--- /dev/null
+++ b/doc/Ledger.scriv/221.rtfd/TXT.rtf
@@ -0,0 +1,12 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;\f1\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 All interactions with the Ledger library take place in the context of a @var\{Session\}. You may create as many sessions as you like, though typically only one is needed during the lifetime of a script
+\f1\fs24 \{\\SCRV_FN=
+\f0\fs28 An example where more might be needed is a GUI program that opens multiple Ledger files in different windows, and creates reports for each file separately
+\f1\fs24 \\END_SCRV_FN\}
+\f0\fs28 . Ledger provides a pre-initialized session named @var\{session\}, but others can still be created. Creating a session is trivial, but before it may be used it must be passed in a call to @code\{set_session_context\}. This is how multiple sessions are managed in a multi-threaded environment, where the session itself should be considered non-reentrant.\
+\
+The first operation after creating a session is typically to load the Ledger data you wish to report on for that session. The loaded data can be reset at any time, and can also be modified.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/222.rtfd/TXT.rtf b/doc/Ledger.scriv/222.rtfd/TXT.rtf
new file mode 100644
index 00000000..0e814392
--- /dev/null
+++ b/doc/Ledger.scriv/222.rtfd/TXT.rtf
@@ -0,0 +1,20 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1038
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 from ledger import *\
+\
+session.read_journal("doc/sample.dat")\
+\
+new_session = Session()\
+\
+set_session_context(new_session)\
+session.read_journal("doc/sample.dat")\
+set_session_content(session) # restore the default session\
+\
+for txn in session.journal.transactions:\
+ print txn.payee\
+\
+ for p in txn.postings:\
+ print p.account, "->", p.amount} \ No newline at end of file
diff --git a/doc/Ledger.scriv/222_synopsis.txt b/doc/Ledger.scriv/222_synopsis.txt
new file mode 100644
index 00000000..4108d440
--- /dev/null
+++ b/doc/Ledger.scriv/222_synopsis.txt
@@ -0,0 +1 @@
+Example of creating a session, reading some journal data, and generating a simplistic report. \ No newline at end of file
diff --git a/doc/Ledger.scriv/23.rtfd/TXT.rtf b/doc/Ledger.scriv/23.rtfd/TXT.rtf
new file mode 100644
index 00000000..b91496a6
--- /dev/null
+++ b/doc/Ledger.scriv/23.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter Value expressions} \ No newline at end of file
diff --git a/doc/Ledger.scriv/24.rtfd/TXT.rtf b/doc/Ledger.scriv/24.rtfd/TXT.rtf
new file mode 100644
index 00000000..b383da33
--- /dev/null
+++ b/doc/Ledger.scriv/24.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter Format strings} \ No newline at end of file
diff --git a/doc/Ledger.scriv/25.rtfd/TXT.rtf b/doc/Ledger.scriv/25.rtfd/TXT.rtf
new file mode 100644
index 00000000..7a41be88
--- /dev/null
+++ b/doc/Ledger.scriv/25.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter Scripting in Python} \ No newline at end of file
diff --git a/doc/Ledger.scriv/26.rtfd/TXT.rtf b/doc/Ledger.scriv/26.rtfd/TXT.rtf
new file mode 100644
index 00000000..1c060c32
--- /dev/null
+++ b/doc/Ledger.scriv/26.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter The design of Ledger} \ No newline at end of file
diff --git a/doc/Ledger.scriv/28.rtfd/TXT.rtf b/doc/Ledger.scriv/28.rtfd/TXT.rtf
new file mode 100644
index 00000000..ec2136a8
--- /dev/null
+++ b/doc/Ledger.scriv/28.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Commands} \ No newline at end of file
diff --git a/doc/Ledger.scriv/29.rtfd/TXT.rtf b/doc/Ledger.scriv/29.rtfd/TXT.rtf
new file mode 100644
index 00000000..35061434
--- /dev/null
+++ b/doc/Ledger.scriv/29.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Options} \ No newline at end of file
diff --git a/doc/Ledger.scriv/30.rtfd/TXT.rtf b/doc/Ledger.scriv/30.rtfd/TXT.rtf
new file mode 100644
index 00000000..5932d491
--- /dev/null
+++ b/doc/Ledger.scriv/30.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Period expressions} \ No newline at end of file
diff --git a/doc/Ledger.scriv/31.rtfd/TXT.rtf b/doc/Ledger.scriv/31.rtfd/TXT.rtf
new file mode 100644
index 00000000..bc261a74
--- /dev/null
+++ b/doc/Ledger.scriv/31.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Format strings} \ No newline at end of file
diff --git a/doc/Ledger.scriv/32.rtfd/TXT.rtf b/doc/Ledger.scriv/32.rtfd/TXT.rtf
new file mode 100644
index 00000000..4e617880
--- /dev/null
+++ b/doc/Ledger.scriv/32.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Value expressions} \ No newline at end of file
diff --git a/doc/Ledger.scriv/33.rtfd/TXT.rtf b/doc/Ledger.scriv/33.rtfd/TXT.rtf
new file mode 100644
index 00000000..3a93ad0c
--- /dev/null
+++ b/doc/Ledger.scriv/33.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section File format} \ No newline at end of file
diff --git a/doc/Ledger.scriv/4.rtfd/TXT.rtf b/doc/Ledger.scriv/4.rtfd/TXT.rtf
new file mode 100644
index 00000000..6923859c
--- /dev/null
+++ b/doc/Ledger.scriv/4.rtfd/TXT.rtf
@@ -0,0 +1,11 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 \\input texinfo @c -*-texinfo-*-\
+\
+@setfilename ledger.info\
+@settitle Ledger: Command-Line Accounting\
+\
+@dircategory User Applications} \ No newline at end of file
diff --git a/doc/Ledger.scriv/44.rtfd/TXT.rtf b/doc/Ledger.scriv/44.rtfd/TXT.rtf
new file mode 100644
index 00000000..1aad7108
--- /dev/null
+++ b/doc/Ledger.scriv/44.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection balance} \ No newline at end of file
diff --git a/doc/Ledger.scriv/5.rtfd/TXT.rtf b/doc/Ledger.scriv/5.rtfd/TXT.rtf
new file mode 100644
index 00000000..4685c038
--- /dev/null
+++ b/doc/Ledger.scriv/5.rtfd/TXT.rtf
@@ -0,0 +1,63 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @copying\
+Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its\
+ 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.\
+@end copying\
+\
+@documentencoding utf-8\
+\
+@iftex\
+@finalout\
+@end iftex\
+\
+@titlepage\
+@title Ledger: Command-Line Accounting\
+@author John Wiegley\
+@end titlepage\
+\
+@direntry\
+* Ledger: (ledger). Command Line Accounting\
+@end direntry\
+\
+@contents\
+\
+@ifnottex\
+@top Overview\
+\
+@insertcopying\
+@end ifnottex\
+\
+@ifnottex\
+@section Copyright\
+@insertcopying\
+@end ifnottex} \ No newline at end of file
diff --git a/doc/Ledger.scriv/54.rtfd/TXT.rtf b/doc/Ledger.scriv/54.rtfd/TXT.rtf
new file mode 100644
index 00000000..e430d8d3
--- /dev/null
+++ b/doc/Ledger.scriv/54.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection register} \ No newline at end of file
diff --git a/doc/Ledger.scriv/55.rtfd/TXT.rtf b/doc/Ledger.scriv/55.rtfd/TXT.rtf
new file mode 100644
index 00000000..2da497e7
--- /dev/null
+++ b/doc/Ledger.scriv/55.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection print} \ No newline at end of file
diff --git a/doc/Ledger.scriv/56.rtfd/TXT.rtf b/doc/Ledger.scriv/56.rtfd/TXT.rtf
new file mode 100644
index 00000000..28f80c59
--- /dev/null
+++ b/doc/Ledger.scriv/56.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection output} \ No newline at end of file
diff --git a/doc/Ledger.scriv/57.rtfd/TXT.rtf b/doc/Ledger.scriv/57.rtfd/TXT.rtf
new file mode 100644
index 00000000..fa709d4e
--- /dev/null
+++ b/doc/Ledger.scriv/57.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection xml} \ No newline at end of file
diff --git a/doc/Ledger.scriv/58.rtfd/TXT.rtf b/doc/Ledger.scriv/58.rtfd/TXT.rtf
new file mode 100644
index 00000000..d6168660
--- /dev/null
+++ b/doc/Ledger.scriv/58.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection emacs} \ No newline at end of file
diff --git a/doc/Ledger.scriv/59.rtfd/TXT.rtf b/doc/Ledger.scriv/59.rtfd/TXT.rtf
new file mode 100644
index 00000000..cb4a9222
--- /dev/null
+++ b/doc/Ledger.scriv/59.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection equity} \ No newline at end of file
diff --git a/doc/Ledger.scriv/6.rtfd/TXT.rtf b/doc/Ledger.scriv/6.rtfd/TXT.rtf
new file mode 100644
index 00000000..e5468e78
--- /dev/null
+++ b/doc/Ledger.scriv/6.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @chapter Introduction} \ No newline at end of file
diff --git a/doc/Ledger.scriv/60.rtfd/TXT.rtf b/doc/Ledger.scriv/60.rtfd/TXT.rtf
new file mode 100644
index 00000000..98fc4024
--- /dev/null
+++ b/doc/Ledger.scriv/60.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection prices} \ No newline at end of file
diff --git a/doc/Ledger.scriv/61.rtfd/TXT.rtf b/doc/Ledger.scriv/61.rtfd/TXT.rtf
new file mode 100644
index 00000000..abfa9470
--- /dev/null
+++ b/doc/Ledger.scriv/61.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection xact} \ No newline at end of file
diff --git a/doc/Ledger.scriv/62.rtfd/TXT.rtf b/doc/Ledger.scriv/62.rtfd/TXT.rtf
new file mode 100644
index 00000000..71f6e89f
--- /dev/null
+++ b/doc/Ledger.scriv/62.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Basic options} \ No newline at end of file
diff --git a/doc/Ledger.scriv/63.rtfd/TXT.rtf b/doc/Ledger.scriv/63.rtfd/TXT.rtf
new file mode 100644
index 00000000..aa512c3c
--- /dev/null
+++ b/doc/Ledger.scriv/63.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Report filtering} \ No newline at end of file
diff --git a/doc/Ledger.scriv/64.rtfd/TXT.rtf b/doc/Ledger.scriv/64.rtfd/TXT.rtf
new file mode 100644
index 00000000..6f46339b
--- /dev/null
+++ b/doc/Ledger.scriv/64.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Output customization} \ No newline at end of file
diff --git a/doc/Ledger.scriv/65.rtfd/TXT.rtf b/doc/Ledger.scriv/65.rtfd/TXT.rtf
new file mode 100644
index 00000000..ddd0f26c
--- /dev/null
+++ b/doc/Ledger.scriv/65.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Commodity reporting} \ No newline at end of file
diff --git a/doc/Ledger.scriv/66.rtfd/TXT.rtf b/doc/Ledger.scriv/66.rtfd/TXT.rtf
new file mode 100644
index 00000000..2d1251f4
--- /dev/null
+++ b/doc/Ledger.scriv/66.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Environment variables} \ No newline at end of file
diff --git a/doc/Ledger.scriv/67.rtfd/TXT.rtf b/doc/Ledger.scriv/67.rtfd/TXT.rtf
new file mode 100644
index 00000000..b960c780
--- /dev/null
+++ b/doc/Ledger.scriv/67.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Variables} \ No newline at end of file
diff --git a/doc/Ledger.scriv/69.rtfd/TXT.rtf b/doc/Ledger.scriv/69.rtfd/TXT.rtf
new file mode 100644
index 00000000..9175b738
--- /dev/null
+++ b/doc/Ledger.scriv/69.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Functions} \ No newline at end of file
diff --git a/doc/Ledger.scriv/7.rtfd/TXT.rtf b/doc/Ledger.scriv/7.rtfd/TXT.rtf
new file mode 100644
index 00000000..342f84d5
--- /dev/null
+++ b/doc/Ledger.scriv/7.rtfd/TXT.rtf
@@ -0,0 +1,125 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 Ledger is an accounting tool with the moxie to exist. It provides no\
+bells or whistles, and returns the user to the days before user\
+interfaces were even a twinkling in their father's CRT.\
+\
+What it does offer is a double-entry accounting ledger with all the\
+flexibility and muscle of its modern day cousins, without any of the\
+fat. Think of it as the Bran Muffin of accounting tools.\
+\
+To use it, you need to start keeping a ledger. This is the basis of\
+all accounting, and if you haven't started yet, now is the time to\
+learn. The little booklet that comes with your checkbook is a ledger,\
+so we'll describe double-entry accounting in terms of that.\
+\
+A checkbook ledger records debits (subtractions, or withdrawals) and\
+credits (additions, or deposits) with reference to a single account:\
+the checking account. Where the money comes from, and where it goes\
+to, are described in the payee field, where you write the person or\
+company's name. The ultimate aim of keeping a checkbook ledger is to\
+know how much money is available to spend. That's really the aim of\
+all ledgers.\
+\
+What computers add is the ability to walk through these postings,\
+and tell you things about your spending habits; to let you devise\
+budgets and get control over your spending; to squirrel away money\
+into virtual savings account without having to physically move money\
+around; etc. As you keep your ledger, you are recording information\
+about your life and habits, and sometimes that information can start\
+telling you things you aren't aware of. Such is the aim of all good\
+accounting tools.\
+\
+The next step up from a checkbook ledger, is a ledger that keeps track\
+of all your accounts, not just checking. In such a ledger, you record\
+not only who gets paid---in the case of a debit---but where the money\
+came from. In a checkbook ledger, its assumed that all the money\
+comes from your checking account. But in a general ledger, you write\
+posting two-lines: the source account and target account.\
+@emph\{There must always be a debit from at least one account for every\
+credit made to another account\}. This is what is meant by\
+``double-entry'' accounting: the ledger must always balance to zero,\
+with an equal number of debits and credits.\
+\
+For example, let's say you have a checking account and a brokerage\
+account, and you can write checks from both of them. Rather than keep\
+two checkbooks, you decide to use one ledger for both. In this\
+general ledger you need to record a payment to Pacific Bell for your\
+monthly phone bill. The cost is $23.00, let's say, and you want to\
+pay it from your checking account. In the general ledger you need to\
+say where the money came from, in addition to where it's going to.\
+The transaction might look like this:\
+\
+@smallexample\
+9/29 BAL Pacific Bell $-200.00 $-200.00\
+ Equity:Opening Balances $200.00\
+9/29 BAL Checking $100.00 $100.00\
+ Equity:Opening Balances $-100.00\
+9/29 100 Pacific Bell $23.00 $223.00\
+ Checking $-23.00 $77.00\
+@end smallexample\
+\
+The first line shows a payment to Pacific Bell for $23.00. Because\
+there is no ``balance'' in a general ledger---it's always zero---we\
+write in the total balance of all payments to ``Pacific Bell'', which\
+now is $223.00 (previously the balance was $200.00). This is done by\
+looking at the last transaction for ``Pacific Bell'' in the ledger, adding\
+$23.00 to that amount, and writing the total in the balance column.\
+And the money came from ``Checking''---a withdrawal of $23.00---which\
+leaves the ending balance in ``Checking'' at $77.00. This is a very\
+manual procedure; but that's where computers come in...\
+\
+The posting must balance to $0: $23 went to Pacific Bell, $23 came\
+from Checking. There is nothing left over to be accounted for, since\
+the money has simply moved from one account to another. This is the\
+basis of double-entry accounting: that money never pops in or out of\
+existence; it is always a posting from one account to another.\
+\
+Keeping a general ledger is the same as keeping two separate ledgers:\
+One for Pacific Bell and one for Checking. In that case, each time a\
+payment is written into one, you write a corresponding withdrawal into\
+the other. This makes it easier to write in a ``running balance'',\
+since you don't have to look back at the last time the account was\
+referenced---but it also means having a lot of ledger books, if you\
+deal with multiple accounts.\
+\
+Enter the beauty of computerized accounting. The purpose of the\
+Ledger program is to make general ledger accounting simple, by keeping\
+track of the balances for you. Your only job is to enter the\
+postings. If a posting does not balance, Ledger displays an\
+error and indicates the incorrect posting.@footnote\{In some\
+special cases, it automatically balances this transaction for you.\}\
+\
+In summary, there are two aspects of Ledger use: updating the ledger\
+data file, and using the Ledger tool to view the summarized result of\
+your transactions.\
+\
+And just for the sake of example---as a starting point for those who\
+want to dive in head-first---here are the ledger transactions from above,\
+formatting as the ledger program wishes to see them:\
+\
+@smallexample\
+2004/09/29 Pacific Bell\
+ Payable:Pacific Bell $-200.00\
+ Equity:Opening Balances\
+\
+2004/09/29 Checking\
+ Accounts:Checking $100.00\
+ Equity:Opening Balances\
+\
+2004/09/29 Pacific Bell\
+ Payable:Pacific Bell $23.00\
+ Accounts:Checking\
+@end smallexample\
+\
+The account balances and registers in this file, if saved as\
+@file\{ledger.dat\}, could be reported using:\
+\
+@example\
+$ ledger -f ledger.dat balance\
+$ ledger -f ledger.dat register checking\
+$ ledger -f ledger.dat register bell\
+@end example} \ No newline at end of file
diff --git a/doc/Ledger.scriv/70.rtfd/TXT.rtf b/doc/Ledger.scriv/70.rtfd/TXT.rtf
new file mode 100644
index 00000000..8a65bc4e
--- /dev/null
+++ b/doc/Ledger.scriv/70.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Operators} \ No newline at end of file
diff --git a/doc/Ledger.scriv/71.rtfd/TXT.rtf b/doc/Ledger.scriv/71.rtfd/TXT.rtf
new file mode 100644
index 00000000..3b81d3af
--- /dev/null
+++ b/doc/Ledger.scriv/71.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Complex expressions} \ No newline at end of file
diff --git a/doc/Ledger.scriv/72.rtfd/TXT.rtf b/doc/Ledger.scriv/72.rtfd/TXT.rtf
new file mode 100644
index 00000000..3bd864ae
--- /dev/null
+++ b/doc/Ledger.scriv/72.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsubsection Posting/account details} \ No newline at end of file
diff --git a/doc/Ledger.scriv/73.rtfd/TXT.rtf b/doc/Ledger.scriv/73.rtfd/TXT.rtf
new file mode 100644
index 00000000..702e47bc
--- /dev/null
+++ b/doc/Ledger.scriv/73.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsubsection Calculated totals} \ No newline at end of file
diff --git a/doc/Ledger.scriv/74.rtfd/TXT.rtf b/doc/Ledger.scriv/74.rtfd/TXT.rtf
new file mode 100644
index 00000000..33cabffb
--- /dev/null
+++ b/doc/Ledger.scriv/74.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Checking balances} \ No newline at end of file
diff --git a/doc/Ledger.scriv/75.rtfd/TXT.rtf b/doc/Ledger.scriv/75.rtfd/TXT.rtf
new file mode 100644
index 00000000..d97237e9
--- /dev/null
+++ b/doc/Ledger.scriv/75.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section The register report} \ No newline at end of file
diff --git a/doc/Ledger.scriv/76.rtfd/TXT.rtf b/doc/Ledger.scriv/76.rtfd/TXT.rtf
new file mode 100644
index 00000000..79bc11fc
--- /dev/null
+++ b/doc/Ledger.scriv/76.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Selecting postings} \ No newline at end of file
diff --git a/doc/Ledger.scriv/77.rtfd/TXT.rtf b/doc/Ledger.scriv/77.rtfd/TXT.rtf
new file mode 100644
index 00000000..b8adc901
--- /dev/null
+++ b/doc/Ledger.scriv/77.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Massaging register output} \ No newline at end of file
diff --git a/doc/Ledger.scriv/78.rtfd/TXT.rtf b/doc/Ledger.scriv/78.rtfd/TXT.rtf
new file mode 100644
index 00000000..dc5a20a8
--- /dev/null
+++ b/doc/Ledger.scriv/78.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Standard queries} \ No newline at end of file
diff --git a/doc/Ledger.scriv/79.rtfd/TXT.rtf b/doc/Ledger.scriv/79.rtfd/TXT.rtf
new file mode 100644
index 00000000..6f79e438
--- /dev/null
+++ b/doc/Ledger.scriv/79.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Reporting balance totals} \ No newline at end of file
diff --git a/doc/Ledger.scriv/8.rtfd/TXT.rtf b/doc/Ledger.scriv/8.rtfd/TXT.rtf
new file mode 100644
index 00000000..70e109c4
--- /dev/null
+++ b/doc/Ledger.scriv/8.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section More introduction} \ No newline at end of file
diff --git a/doc/Ledger.scriv/80.rtfd/TXT.rtf b/doc/Ledger.scriv/80.rtfd/TXT.rtf
new file mode 100644
index 00000000..47824727
--- /dev/null
+++ b/doc/Ledger.scriv/80.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Reporting percentages} \ No newline at end of file
diff --git a/doc/Ledger.scriv/81.rtfd/TXT.rtf b/doc/Ledger.scriv/81.rtfd/TXT.rtf
new file mode 100644
index 00000000..f0294dd7
--- /dev/null
+++ b/doc/Ledger.scriv/81.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Sub-account balances} \ No newline at end of file
diff --git a/doc/Ledger.scriv/82.rtfd/TXT.rtf b/doc/Ledger.scriv/82.rtfd/TXT.rtf
new file mode 100644
index 00000000..2ab3f745
--- /dev/null
+++ b/doc/Ledger.scriv/82.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Specific account balances} \ No newline at end of file
diff --git a/doc/Ledger.scriv/83.rtfd/TXT.rtf b/doc/Ledger.scriv/83.rtfd/TXT.rtf
new file mode 100644
index 00000000..4cb67c37
--- /dev/null
+++ b/doc/Ledger.scriv/83.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Specific register queries} \ No newline at end of file
diff --git a/doc/Ledger.scriv/84.rtfd/TXT.rtf b/doc/Ledger.scriv/84.rtfd/TXT.rtf
new file mode 100644
index 00000000..751f7f5e
--- /dev/null
+++ b/doc/Ledger.scriv/84.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection By date} \ No newline at end of file
diff --git a/doc/Ledger.scriv/85.rtfd/TXT.rtf b/doc/Ledger.scriv/85.rtfd/TXT.rtf
new file mode 100644
index 00000000..dbeb4244
--- /dev/null
+++ b/doc/Ledger.scriv/85.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection By status} \ No newline at end of file
diff --git a/doc/Ledger.scriv/86.rtfd/TXT.rtf b/doc/Ledger.scriv/86.rtfd/TXT.rtf
new file mode 100644
index 00000000..974179b9
--- /dev/null
+++ b/doc/Ledger.scriv/86.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection By relationship} \ No newline at end of file
diff --git a/doc/Ledger.scriv/87.rtfd/TXT.rtf b/doc/Ledger.scriv/87.rtfd/TXT.rtf
new file mode 100644
index 00000000..0b429d5c
--- /dev/null
+++ b/doc/Ledger.scriv/87.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection By budget} \ No newline at end of file
diff --git a/doc/Ledger.scriv/88.rtfd/TXT.rtf b/doc/Ledger.scriv/88.rtfd/TXT.rtf
new file mode 100644
index 00000000..be28f009
--- /dev/null
+++ b/doc/Ledger.scriv/88.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection By value expression} \ No newline at end of file
diff --git a/doc/Ledger.scriv/89.rtfd/TXT.rtf b/doc/Ledger.scriv/89.rtfd/TXT.rtf
new file mode 100644
index 00000000..ba2ddc55
--- /dev/null
+++ b/doc/Ledger.scriv/89.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Summarizing} \ No newline at end of file
diff --git a/doc/Ledger.scriv/9.rtfd/TXT.rtf b/doc/Ledger.scriv/9.rtfd/TXT.rtf
new file mode 100644
index 00000000..c399f72d
--- /dev/null
+++ b/doc/Ledger.scriv/9.rtfd/TXT.rtf
@@ -0,0 +1,55 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 The most important part of accounting is keeping a good ledger. If\
+you have a good ledger, tools can be written to work whatever\
+mathematically tricks you need to better understand your spending\
+patterns. Without a good ledger, no tool, however smart, can help\
+you.\
+\
+The Ledger program aims at making ledger transaction as simple as possible.\
+Since it is a command-line tool, it does not provide a user interface\
+for keeping a ledger. If you like, you may use GnuCash to maintain\
+your ledger, in which case the Ledger program will read GnuCash's data\
+files directly. In that case, read the GnuCash manual now, and skip\
+to the next chapter.\
+\
+If you are not using GnuCash, but a text editor to maintain your\
+ledger, read on. Ledger has been designed to make data transaction as\
+simple as possible, by keeping the ledger format easy, and also by\
+automagically determining as much information as possible based on the\
+nature of your transactions.\
+\
+For example, you do not need to tell Ledger about the accounts you\
+use. Any time Ledger sees a posting involving an account it knows\
+nothing about, it will create it. If you use a commodity that is new\
+to Ledger, it will create that commodity, and determine its display\
+characteristics (placement of the symbol before or after the amount,\
+display precision, etc) based on how you used the commodity in the\
+posting.\
+\
+Here is the Pacific Bell example from above, given as a Ledger\
+posting:\
+\
+@smallexample\
+9/29 (100) Pacific Bell\
+ Expenses:Utilities:Phone $23.00\
+ Assets:Checking $-23.00\
+@end smallexample\
+\
+As you can see, it is very similar to what would be written on paper,\
+minus the computed balance totals, and adding in account names that\
+work better with Ledger's scheme of things. In fact, since Ledger is\
+smart about many things, you don't need to specify the balanced\
+amount, if it is the same as the first line:\
+\
+@smallexample\
+9/29 (100) Pacific Bell\
+ Expenses:Utilities:Phone $23.00\
+ Assets:Checking\
+@end smallexample\
+\
+For this transaction, Ledger will figure out that $-23.00 must come from\
+@samp\{Assets:Checking\} in order to balance the transaction.} \ No newline at end of file
diff --git a/doc/Ledger.scriv/90.rtfd/TXT.rtf b/doc/Ledger.scriv/90.rtfd/TXT.rtf
new file mode 100644
index 00000000..44515219
--- /dev/null
+++ b/doc/Ledger.scriv/90.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Quick periods} \ No newline at end of file
diff --git a/doc/Ledger.scriv/91.rtfd/TXT.rtf b/doc/Ledger.scriv/91.rtfd/TXT.rtf
new file mode 100644
index 00000000..89359299
--- /dev/null
+++ b/doc/Ledger.scriv/91.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Ordering and width} \ No newline at end of file
diff --git a/doc/Ledger.scriv/92.rtfd/TXT.rtf b/doc/Ledger.scriv/92.rtfd/TXT.rtf
new file mode 100644
index 00000000..3be475eb
--- /dev/null
+++ b/doc/Ledger.scriv/92.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Averages and percentages} \ No newline at end of file
diff --git a/doc/Ledger.scriv/93.rtfd/TXT.rtf b/doc/Ledger.scriv/93.rtfd/TXT.rtf
new file mode 100644
index 00000000..e65afe62
--- /dev/null
+++ b/doc/Ledger.scriv/93.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Reporting total data} \ No newline at end of file
diff --git a/doc/Ledger.scriv/94.rtfd/TXT.rtf b/doc/Ledger.scriv/94.rtfd/TXT.rtf
new file mode 100644
index 00000000..3167bece
--- /dev/null
+++ b/doc/Ledger.scriv/94.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Display by value expression} \ No newline at end of file
diff --git a/doc/Ledger.scriv/95.rtfd/TXT.rtf b/doc/Ledger.scriv/95.rtfd/TXT.rtf
new file mode 100644
index 00000000..44f588f4
--- /dev/null
+++ b/doc/Ledger.scriv/95.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Change report format} \ No newline at end of file
diff --git a/doc/Ledger.scriv/96.rtfd/TXT.rtf b/doc/Ledger.scriv/96.rtfd/TXT.rtf
new file mode 100644
index 00000000..d5d4f345
--- /dev/null
+++ b/doc/Ledger.scriv/96.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Stating where money goes} \ No newline at end of file
diff --git a/doc/Ledger.scriv/97.rtfd/TXT.rtf b/doc/Ledger.scriv/97.rtfd/TXT.rtf
new file mode 100644
index 00000000..4b4d44d7
--- /dev/null
+++ b/doc/Ledger.scriv/97.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Assets and Liabilities} \ No newline at end of file
diff --git a/doc/Ledger.scriv/98.rtfd/TXT.rtf b/doc/Ledger.scriv/98.rtfd/TXT.rtf
new file mode 100644
index 00000000..0c3129c3
--- /dev/null
+++ b/doc/Ledger.scriv/98.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @subsection Tracking reimbursable expenses} \ No newline at end of file
diff --git a/doc/Ledger.scriv/99.rtfd/TXT.rtf b/doc/Ledger.scriv/99.rtfd/TXT.rtf
new file mode 100644
index 00000000..0c756876
--- /dev/null
+++ b/doc/Ledger.scriv/99.rtfd/TXT.rtf
@@ -0,0 +1,6 @@
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\fonttbl\f0\fmodern\fcharset0 Courier;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl264\slmult1\ql\qnatural\pardirnatural
+
+\f0\fs28 \cf0 @section Typical queries} \ No newline at end of file
diff --git a/doc/Ledger.scriv/BinderStrings.xml b/doc/Ledger.scriv/BinderStrings.xml
new file mode 100644
index 00000000..7b753473
--- /dev/null
+++ b/doc/Ledger.scriv/BinderStrings.xml
@@ -0,0 +1,5741 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>100</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Reporting monthly expenses</string>
+ <key>Title</key>
+ <string>Reporting monthly expenses</string>
+ </dict>
+ <key>101</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Visualizing with Gnuplot</string>
+ <key>Title</key>
+ <string>Visualizing with Gnuplot</string>
+ </dict>
+ <key>102</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsubsection Typical plots</string>
+ <key>Title</key>
+ <string>Typical plots</string>
+ </dict>
+ <key>103</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Budgeting and forecasting</string>
+ <key>Title</key>
+ <string>Budgeting and forecasting</string>
+ </dict>
+ <key>104</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Budgeting</string>
+ <key>Title</key>
+ <string>Budgeting</string>
+ </dict>
+ <key>105</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Forecasting</string>
+ <key>Title</key>
+ <string>Forecasting</string>
+ </dict>
+ <key>106</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Commodities and Currencies</string>
+ <key>Title</key>
+ <string>Commodities and Currencies</string>
+ </dict>
+ <key>107</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Commodity price histories</string>
+ <key>Title</key>
+ <string>Commodity price histories</string>
+ </dict>
+ <key>108</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Commodity equivalencies</string>
+ <key>Title</key>
+ <string>Commodity equivalencies</string>
+ </dict>
+ <key>109</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Accounts and Inventories</string>
+ <key>Title</key>
+ <string>Accounts and Inventories</string>
+ </dict>
+ <key>110</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Understanding Equity</string>
+ <key>Title</key>
+ <string>Understanding Equity</string>
+ </dict>
+ <key>111</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Dealing with Petty Cash</string>
+ <key>Title</key>
+ <string>Dealing with Petty Cash</string>
+ </dict>
+ <key>112</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Working with multiple funds and accounts</string>
+ <key>Title</key>
+ <string>Working with multiple funds and accounts</string>
+ </dict>
+ <key>113</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Archiving previous years</string>
+ <key>Title</key>
+ <string>Archiving previous years</string>
+ </dict>
+ <key>114</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Virtual postings</string>
+ <key>Title</key>
+ <string>Virtual postings</string>
+ </dict>
+ <key>115</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Automated postings</string>
+ <key>Title</key>
+ <string>Automated postings</string>
+ </dict>
+ <key>116</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Using Emacs to Keep Your Ledger</string>
+ <key>Title</key>
+ <string>Using Emacs to Keep Your Ledger</string>
+ </dict>
+ <key>117</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Using GnuCash to Keep Your Ledger</string>
+ <key>Title</key>
+ <string>Using GnuCash to Keep Your Ledger</string>
+ </dict>
+ <key>118</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Using timeclock to record billable time</string>
+ <key>Title</key>
+ <string>Using timeclock to record billable time</string>
+ </dict>
+ <key>119</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Using XML</string>
+ <key>Title</key>
+ <string>Using XML</string>
+ </dict>
+ <key>12</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Building the program</string>
+ <key>Title</key>
+ <string>Building the program</string>
+ </dict>
+ <key>120</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Numerics</string>
+ <key>Title</key>
+ <string>Numerics</string>
+ </dict>
+ <key>121</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Basic amounts</string>
+ <key>Title</key>
+ <string>Basic amounts</string>
+ </dict>
+ <key>122</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Journal Representation</string>
+ <key>Title</key>
+ <string>Journal Representation</string>
+ </dict>
+ <key>123</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Reporting</string>
+ <key>Title</key>
+ <string>Reporting</string>
+ </dict>
+ <key>124</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Terminal Interface</string>
+ <key>Title</key>
+ <string>Terminal Interface</string>
+ </dict>
+ <key>125</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section General Utility</string>
+ <key>Title</key>
+ <string>General Utility</string>
+ </dict>
+ <key>126</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>This chapter describes ledger's features and serves as a quick
+reference. You may wish to survey this to get an overview before diving
+in to the @ref{Ledger Tutorial} and more detailed examples that follow.
+
+Ledger has a very simple command-line interface, named---enticing
+enough---@command{ledger}. It supports a few reporting commands, and
+a large number of options for refining the output from those commands.
+The basic syntax of any ledger command is:
+
+@example
+ledger [OPTIONS...] COMMAND [ARGS...]
+@end example
+
+Command options must always precede the command word. After the
+command word there may appear any number of arguments. For most
+commands, these arguments are regular expressions that cause the
+output to relate only to postings matching those regular
+expressions. For the @command{transaction} command, the arguments have a
+special meaning, described below.
+
+The regular expressions arguments always match the account name that a
+posting refers to. To match on the payee of the transaction instead,
+precede the regular expression with @samp{--}. For example, the
+following balance command reports account totals for rent, food and
+movies, but only those whose payee matches Freddie:
+
+@example
+ledger bal rent food movies -- freddie
+@end example
+
+There are many, many command options available with the
+@command{ledger} command, and it takes a while to master them.
+However, none of them are required to use the basic reporting
+commands.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>128</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The @command{balance} command reports the current balance of all
+accounts. It accepts a list of optional regexps, which confine the
+balance report to the matching accounts. If an account contains
+multiple types of commodities, each commodity's total is reported
+separately.
+</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>129</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The @command{register} command displays all the postings occurring
+in a single account, line by line. The account regexp must be
+specified as the only argument to this command. If any regexps occur
+after the required account name, the register will contain only those
+postings that match. Very useful for hunting down a particular
+posting.
+
+The output from @command{register} is very close to what a typical
+checkbook, or single-account ledger, would look like. It also shows a
+running balance. The final running balance of any register should
+always be the same as the current balance of that account.
+
+If you have Gnuplot installed, you may plot the amount or running
+total of any register by using the script @file{report}, which is
+included in the Ledger distribution. The only requirement is that you
+add either @option{-j} or @option{-J} to your register command, in
+order to plot either the amount or total column, respectively.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>13</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Getting help</string>
+ <key>Title</key>
+ <string>Getting help</string>
+ </dict>
+ <key>130</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The @command{print} command prints out ledger transactions in a textual
+format that can be parsed by Ledger. They will be properly formatted,
+and output in the most economic form possible. The ``print'' command
+also takes a list of optional regexps, which will cause only those
+postings which match in some way to be printed.
+
+The @command{print} command can be a handy way to clean up a ledger
+file whose formatting has gotten out of hand.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>131</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The @command{output} command is very similar to the @command{print}
+command, except that it attempts to replicate the specified ledger
+file epostly. The format of the command is:
+
+@example
+ledger -f FILENAME output FILENAME
+@end example
+
+Where @file{FILENAME} is the name of the ledger file to output. The
+reason for specifying this command is that only transactions contained
+within that file will be output, and not an included transactions (as can
+happen with the @command{print} command).</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>132</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The @command{xml} command outputs results similar to what
+@command{print} and @command{register} display, but as an XML form.
+This data can then be read in and processed. Use the
+@option{--totals} option to include the running total with each
+posting.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>133</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The @command{emacs} command outputs results in a form that can be read
+directly by Emacs Lisp. The format of the sexp is:
+
+@example
+((BEG-POS CLEARED DATE CODE PAYEE
+ (ACCOUNT AMOUNT)...) ; list of postings
+ ...) ; list of transactions
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>134</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The @command{equity} command prints out accounts balances as if they
+were transactions. This makes it easy to establish the starting balances
+for an account, such as when @ref{Archiving previous years}.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>135</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The @command{prices} command displays the price history for matching
+commodities. The @option{-A} flag is useful with this report, to
+display the running average price, or @option{-D} to show each price's
+deviation from that average.
+
+There is also a @command{pricesdb} command which outputs the same
+information as @command{prices}, but does in a format that can be
+parsed by Ledger.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>136</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The @command{xact} commands simplifies the creation of new transactions.
+It works on the principle that 80% of all postings are variants of
+earlier postings. Here's how it works:
+
+Say you currently have this posting in your ledger file:
+
+@smallexample
+2004/03/15 * Viva Italiano
+ Expenses:Food $12.45
+ Expenses:Tips $2.55
+ Liabilities:MasterCard $-15.00
+@end smallexample
+
+Now it's @samp{2004/4/9}, and you've just eating at @samp{Viva
+Italiano} again. The epost amounts are different, but the overall
+form is the same. With the @command{xact} command you can type:
+
+@example
+ledger xact 2004/4/9 viva food 11 tips 2.50
+@end example
+
+This produces the following output:
+
+@smallexample
+2004/04/09 Viva Italiano
+ Expenses:Food $11.00
+ Expenses:Tips $2.50
+ Liabilities:MasterCard $-13.50
+@end smallexample
+
+It works by finding a past posting matching the regular expression
+@samp{viva}, and assuming that any accounts or amounts specified will
+be similar to that earlier posting. If Ledger does not succeed in
+generating a new transaction, an error is printed and the exit code is set
+to @samp{1}.
+
+There is a shell script in the distribution's @file{scripts} directory
+called @file{xact}, which simplifies the task of adding a new transaction
+to your ledger. It launches @command{vi} to confirm that the transaction
+looks appropriate.
+
+Here are a few more examples of the @command{xact} command, assuming
+the above journal transaction:
+
+@example
+ledger xact 4/9 viva 11.50
+ledger xact 4/9 viva 11.50 checking # (from `checking')
+ledger xact 4/9 viva food 11.50 tips 8
+ledger xact 4/9 viva food 11.50 tips 8 cash
+ledger xact 4/9 viva food $11.50 tips $8 cash
+ledger xact 4/9 viva dining "DM 11.50"
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>137</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>With all of the reports, command-line options are useful to modify the
+output generated. These command-line options always occur before the
+command word. This is done to distinguish options from exclusive
+regular expressions, which also begin with a dash. The basic form for
+most commands is:
+
+@example
+ledger [OPTIONS] COMMAND [REGEXPS...] [-- [REGEXPS...]]
+@end example
+
+The @var{OPTIONS} and @var{REGEXPS} expressions are both optional.
+You could just use @samp{ledger balance}, without any options---which
+prints a summary of all accounts. But for more specific reporting, or
+to change the appearance of the output, options are needed.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>138</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>These are the most basic command options. Most likely, the user will
+want to set them using environment variables (see @ref{Options}),
+instead of using actual command-line options:
+
+@option{--help} (@option{-h}) prints a summary of all the options, and
+what they are used for. This can be a handy way to remember which
+options do what. This help screen is also printed if ledger is run
+without a command.
+
+@option{--version} (@option{-v}) prints the current version of ledger
+and exits. This is useful for sending bug reports, to let the author
+know which version of ledger you are using.
+
+@option{--file FILE} (@option{-f FILE}) reads FILE as a ledger file.
+This command may be used multiple times. FILE may also be a list of
+file names separated by colons. Typically, the environment variable
+@env{LEDGER_FILE} is set, rather than using this command-line option.
+
+@option{--output FILE} (@option{-o FILE}) redirects output from any
+command to @var{FILE}. By default, all output goes to standard
+output.
+
+@option{--init-file FILE} (@option{-i FILE}) causes FILE to be read by
+ledger before any other ledger file. This file may not contain any
+postings, but it may contain option settings. To specify options
+in the init file, use the same syntax as the command-line. Here's an
+example init file:
+
+@smallexample
+--price-db ~/finance/.pricedb
+
+; ~/.ledgerrc ends here
+@end smallexample
+
+Option settings on the command-line or in the environment always take
+precedence over settings in the init file.
+
+@option{--cache FILE} identifies FILE as the default binary cache
+file. That is, if the ledger files to be read are specified using the
+environment variable @env{LEDGER_FILE}, then whenever a command is
+finished a binary copy will be written to the specified cache, to
+speed up the loading time of subsequent queries. This filename can
+also be given using the environment variable @env{LEDGER_CACHE}, or by
+putting the option into your init file. The @option{--no-cache}
+option causes Ledger to always ignore the binary cache.
+
+@option{--account NAME} (@option{-a NAME}) specifies the default
+account which QIF file postings are assumed to relate to.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>139</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>These options change which postings affect the outcome of a
+report, in ways other than just using regular expressions:
+
+@option{--current}(@option{-c}) displays only transactions occurring on or
+before the current date.
+
+@option{--begin DATE} (@option{-b DATE}) constrains the report to
+transactions on or after @var{DATE}. Only transactions after that date will be
+calculated, which means that the running total in the balance report
+will always start at zero with the first matching transaction. (Note: This
+is different from using @option{--display} to constrain what is
+displayed).
+
+@option{--end DATE} (@option{-e DATE}) constrains the report so that
+transactions on or after @var{DATE} are not considered. The ending date
+is inclusive.
+
+@option{--period STR} (@option{-p STR}) sets the reporting period
+to @var{STR}. This will subtotal all matching transactions within each
+period separately, making it easy to see weekly, monthly, quarterly,
+etc., posting totals. A period string can even specify the
+beginning and end of the report range, using simple terms like ``last
+june'' or ``next month''. For more using period expressions, see
+@ref{Period expressions}.
+
+@option{--period-sort EXPR} sorts the postings within each
+reporting period using the value expression @var{EXPR}. This is most
+often useful when reporting monthly expenses, in order to view the
+highest expense categories at the top of each month:
+
+@example
+ledger -M --period-sort -At reg ^Expenses
+@end example
+
+@option{--cleared} (@option{-C}) displays only postings whose transaction
+has been marked ``cleared'' (by placing an asterix to the right of the
+date).
+
+@option{--uncleared} (@option{-U}) displays only postings whose
+transaction has not been marked ``cleared'' (i.e., if there is no asterix to
+the right of the date).
+
+@option{--real} (@option{-R}) displays only real postings, not
+virtual. (A virtual posting is indicated by surrounding the
+account name with parentheses or brackets; see the section on using
+virtual postings for more information).
+
+@option{--actual} (@option{-L}) displays only actual postings, and
+not those created due to automated postings.
+
+@option{--related} (@option{-r}) displays postings that are
+related to whichever postings would otherwise have matched the
+filtering criteria. In the register report, this shows where money
+went to, or the account it came from. In the balance report, it shows
+all the accounts affected by transactions having a related posting.
+For example, if a file had this transaction:
+
+@smallexample
+2004/03/20 Safeway
+ Expenses:Food $65.00
+ Expenses:Cash $20.00
+ Assets:Checking $-85.00
+@end smallexample
+
+And the register command was:
+
+@example
+ledger -r register food
+@end example
+
+The following would be output, showing the postings related to the
+posting that matched:
+
+@smallexample
+2004/03/20 Safeway Expenses:Cash $-20.00 $-20.00
+ Assets:Checking $85.00 $65.00
+@end smallexample
+
+@option{--budget} is useful for displaying how close your postings
+meet your budget. @option{--add-budget} also shows unbudgeted
+postings, while @option{--unbudgeted} shows only those.
+@option{--forecast} is a related option that projects your budget into
+the future, showing how it will affect future balances.
+@xref{Budgeting and forecasting}.
+
+@option{--limit EXPR} (@option{-l EXPR}) limits which postings
+take part in the calculations of a report.
+
+@option{--amount EXPR} (@option{-t EXPR}) changes the value expression
+used to calculate the ``value'' column in the @command{register}
+report, the amount used to calculate account totals in the
+@command{balance} report, and the values printed in the
+@command{equity} report. @xref{Value expressions}.
+
+@option{--total EXPR} (@option{-T EXPR}) sets the value expression
+used for the ``totals'' column in the @command{register} and
+@command{balance} reports.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>14</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Ledger is written in ANSI C++, and should compile on any platform. It
+depends on the GNU multiprecision integer library (libgmp), and the
+Perl regular expression library (libpcre). It was developed using GNU
+make and gcc 3.3, on a PowerBook running OS/X.
+
+To build and install once you have these libraries on your system,
+enter these commands:
+
+@example
+./configure &amp;&amp; make install
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>140</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>These options affect only the output, but not which postings are
+used to create it:
+
+@option{--collapse} (@option{-n}) causes transactions in a
+@command{register} report with multiple postings to be collapsed
+into a single, subtotaled transaction.
+
+@option{--subtotal} (@option{-s}) causes all transactions in a
+@command{register} report to be collapsed into a single, subtotaled
+transaction.
+
+@option{--by-payee} (@option{-P}) reports subtotals by payee.
+
+@option{--comm-as-payee} (@option{-x}) changes the payee of every
+posting to be the commodity used in that posting. This can be
+useful when combined with other options, such as @option{-s}.
+
+@option{--empty} (@option{-E}) includes even empty accounts in the
+@command{balance} report.
+
+@option{--weekly} (@option{-W}) reports posting totals by the
+week. The week begins on whichever day of the week begins the month
+containing that posting. To set a specific begin date, use a
+period string, such as @samp{weekly from DATE}. @option{--monthly}
+(@option{-M}) reports posting totals by month; @option{--yearly}
+(@option{-Y}) reports posting totals by year. For more complex
+period, using the @option{--period} option described above.
+
+@option{--dow} reports postings totals for each day of the week.
+This is an easy way to see if weekend spending is more than on
+weekdays.
+
+@option{--sort EXPR} (@option{-S EXPR}) sorts a report by comparing
+the values determined using the value expression @var{EXPR}. For
+example, using @option{-S -UT} in the balance report will sort account
+balances from greatest to least, using the absolute value of the
+total. For more on how to use value expressions, see @ref{Value
+expressions}.
+
+@option{--wide} (@option{-w}) causes the default @command{register}
+report to assume 132 columns instead of 80.
+
+@option{--head} causes only the first N transactions to be printed. This
+is different from using the command-line utility @command{head}, which
+would limit to the first N postings. @option{--tail} outputs only
+the last N transactions. Both options may be used simultaneously. If a
+negative amount is given, it will invert the meaning of the flag
+(instead of the first five transactions being printed, for example, it
+would print all but the first five).
+
+@option{--pager} tells Ledger to pass its output to the given pager
+program---very useful when the output is especially long. This
+behavior can be made the default by setting the @env{LEDGER_PAGER}
+environment variable.
+
+@option{--average} (@option{-A}) reports the average posting
+value.
+
+@option{--deviation} (@option{-D}) reports each posting's
+deviation from the average. It is only meaningful in the
+@command{register} and @command{prices} reports.
+
+@option{--percentage} (@option{-%}) shows account subtotals in the
+@command{balance} report as percentages of the parent account.
+
+@option{--totals} include running total information in the
+@command{xml} report.
+
+@option{--amount-data} (@option{-j}) changes the @command{register}
+report so that it output nothing but the date and the value column,
+and the latter without commodities. This is only meaningful if the
+report uses a single commodity. This data can then be fed to other
+programs, which could plot the date, analyze it, etc.
+
+@option{--total-data} (@option{-J}) changes the @command{register}
+report so that it output nothing but the date and totals column,
+without commodities.
+
+@option{--display EXPR} (@option{-d EXPR}) limits which postings
+or accounts or actually displayed in a report. They might still be
+calculated, and be part of the running total of a register report, for
+example, but they will not be displayed. This is useful for seeing
+last month's checking postings, against a running balance which
+includes all posting values:
+
+@example
+ledger -d "d&gt;=[last month]" reg checking
+@end example
+
+The output from this command is very different from the following,
+whose running total includes only postings from the last month
+onward:
+
+@example
+ledger -p "last month" reg checking
+@end example
+
+Which is more useful depends on what you're looking to know: the total
+amount for the reporting range (@option{-p}), or simply a display
+restricted to the reporting range (using @option{-d}).
+
+@option{--date-format STR} (@option{-y STR}) changes the basic date
+format used by reports. The default uses a date like 2004/08/01,
+which represents the default date format of @samp{%Y/%m/%d}. To
+change the way dates are printed in general, the easiest way is to put
+@option{--date-format FORMAT} in the Ledger initialization file
+@file{~/.ledgerrc} (or the file referred to by @env{LEDGER_INIT}).
+
+@option{--format STR} (@option{-F STR}) sets the reporting format for
+whatever report ledger is about to make. @xref{Format strings}.
+There are also specific format commands for each report type:
+
+@itemize
+@item @option{--balance-format STR}
+@item @option{--register-format STR}
+@item @option{--print-format STR}
+@item @option{--plot-amount-format STR} (-j @command{register})
+@item @option{--plot-total-format STR} (-J @command{register})
+@item @option{--equity-format STR}
+@item @option{--prices-format STR}
+@item @option{--wide-register-format STR} (-w @command{register})
+@end itemize</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>141</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>These options affect how commodity values are displayed:
+
+@option{--price-db FILE} sets the file that is used for recording
+downloaded commodity prices. It is always read on startup, to
+determine historical prices. Other settings can be placed in this
+file manually, to prevent downloading quotes for a specific, for
+example. This is done by adding a line like the following:
+
+@example
+; Don't download quotes for the dollar, or timelog values
+N $
+N h
+@end example
+
+@option{--price-exp MINS} (@option{-L MINS}) sets the expected
+freshness of price quotes, in minutes. That is, if the last known
+quote for any commodity is older than this value---and if
+@option{--download} is being used---then the Internet will be
+consulted again for a newer price. Otherwise, the old price is still
+considered to be fresh enough.
+
+@option{--download} (@option{-Q}) causes quotes to be automagically
+downloaded, as needed, by running a script named @command{getquote}
+and expecting that script to return a value understood by ledger. A
+sample implementation of a @command{getquote} script, implemented in
+Perl, is provided in the distribution. Downloaded quote price are
+then appended to the price database, usually specified using the
+environment variable @env{LEDGER_PRICE_DB}.
+
+There are several different ways that ledger can report the totals it
+displays. The most flexible way to adjust them is by using value
+expressions, and the @option{-t} and @option{-T} options. However,
+there are also several ``default'' reports, which will satisfy most
+users basic reporting needs:
+
+@table @code
+@item -O, --quantity
+Reports commodity totals (this is the default)
+
+@item -B, --basis
+Reports the cost basis for all postings.
+
+@item -V, --market
+Reports the last known market value for all commodities.
+
+@item -G --gain
+Reports the net gain/loss for all commodities in the report that have
+a price history.
+@end table</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>142</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Every option to ledger may be set using an environment variable. If
+an option has a long name such @option{--this-option}, setting the
+environment variable @env{LEDGER_THIS_OPTION} will have the same
+affect as specifying that option on the command-line. Options on the
+command-line always take precedence over environment variable
+settings, however.
+
+Note that you may also permanently specify option values by placing
+option settings in the file @file{~/.ledgerrc}, for example:
+
+@example
+--cache /tmp/.mycache
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>143</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>A period expression indicates a span of time, or a reporting interval,
+or both. The full syntax is:
+
+@example
+[INTERVAL] [BEGIN] [END]
+@end example
+
+The optional @var{INTERVAL} part may be any one of:
+
+@example
+every day
+every week
+every monthly
+every quarter
+every year
+every N days # N is any integer
+every N weeks
+every N months
+every N quarters
+every N years
+daily
+weekly
+biweekly
+monthly
+bimonthly
+quarterly
+yearly
+@end example
+
+After the interval, a begin time, end time, both or neither may be
+specified. As for the begin time, it can be either of:
+
+@example
+from &lt;SPEC&gt;
+since &lt;SPEC&gt;
+@end example
+
+The end time can be either of:
+
+@example
+to &lt;SPEC&gt;
+until &lt;SPEC&gt;
+@end example
+
+Where @var{SPEC} can be any of:
+
+@example
+2004
+2004/10
+2004/10/1
+10/1
+october
+oct
+this week # or day, month, quarter, year
+next week
+last week
+@end example
+
+The beginning and ending can be given at the same time, if it spans a
+single period. In that case, just use @var{SPEC} by itself. In that
+case, the period @samp{oct}, for example, will cover all the days in
+october. The possible forms are:
+
+@example
+&lt;SPEC&gt;
+in &lt;SPEC&gt;
+@end example
+
+Here are a few examples of period expressions:
+
+@example
+monthly
+monthly in 2004
+weekly from oct
+weekly from last month
+from sep to oct
+from 10/1 to 10/5
+monthly until 2005
+from apr
+until nov
+last oct
+weekly last august
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>144</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Format strings may be used to change the output format of reports.
+They are specified by passing a formatting string to the
+@option{--format} (@option{-F}) option. Within that string,
+constructs are allowed which make it possible to display the various
+parts of an account or posting in custom ways.
+
+Within a format strings, a substitution is specified using a percent
+character (@samp{%}). The basic format of all substitutions is:
+
+@example
+%[-][MIN WIDTH][.MAX WIDTH]EXPR
+@end example
+
+If the optional minus sign (@samp{-}) follows the percent character,
+whatever is substituted will be left justified. The default is right
+justified. If a minimum width is given next, the substituted text
+will be at least that wide, perhaps wider. If a period and a maximum
+width is given, the substituted text will never be wider than this,
+and will be truncated to fit. Here are some examples:
+
+@example
+%-P a transaction's payee, left justified
+%20P The same, right justified, at least 20 chars wide
+%.20P The same, no more than 20 chars wide
+%-.20P Left justified, maximum twenty chars wide
+@end example
+
+The expression following the format constraints can be a single
+letter, or an expression enclosed in parentheses or brackets. The
+allowable expressions are:
+
+@table @code
+@item %
+Inserts a percent sign.
+
+@item t
+Inserts the results of the value expression specified by @option{-t}.
+If @option{-t} was not specified, the current report style's value
+expression is used.
+
+@item T
+Inserts the results of the value expression specified by @option{-T}.
+If @option{-T} was not specified, the current report style's value
+expression is used.
+
+@item |
+Inserts a single space. This is useful if a width is specified, for
+inserting a certain number of spaces.
+
+@item _
+Inserts a space for each level of an account's depth. That is, if an
+account has two parents, this construct will insert two spaces. If a
+minimum width is specified, that much space is inserted for each level
+of depth. Thus @samp{%5_}, for an account with four parents, will
+insert twenty spaces.
+
+@item (EXPR)
+Inserts the amount resulting from the value expression given in
+parentheses. To insert five times the total value of an account, for
+example, one could say @samp{%12(5*O)}. Note: It's important to put
+the five first in that expression, so that the commodity doesn't get
+stripped from the total.
+
+@item [DATEFMT]
+Inserts the result of formatting a posting's date with a date
+format string, epostly like those supported by @code{strftime}. For
+example: @samp{%[%Y/%m/%d %H:%M:%S]}.
+
+@item S
+Insert the pathname of the file from which the transaction's data was read.
+
+@item B
+Inserts the beginning character position of that transaction within the file.
+
+@item b
+Inserts the beginning line of that transaction within the file.
+
+@item E
+Inserts the ending character position of that transaction within the file.
+
+@item e
+Inserts the ending line of that transaction within the file.
+
+@item D
+By default, this is the same as @samp{%[%Y/%m%/d]}. The date format
+used can be changed at any time with the @option{-y} flag, however.
+Using @samp{%D} gives the user more control over the way dates are
+output.
+
+@item d
+This is the same as the @samp{%D} option, unless the transaction has an
+effective date, in which case it prints
+@samp{[ACTUAL_DATE=EFFECtIVE_DATE]}.
+
+@item X
+If a posting has been cleared, this inserts @samp{*} followed by a
+space; otherwise nothing is inserted.
+
+@item Y
+This is the same as @samp{%X}, except that it only displays a state
+character if all of the member postings have the same state.
+
+@item C
+Inserts the checking number for a transaction, in parentheses, followed by
+a space; if none was specified, nothing is inserted.
+
+@item P
+Inserts the payee related to a posting.
+
+@item a
+Inserts the optimal short name for an account. This is normally used
+in balance reports. It prints a parent account's name if that name
+has not been printed yet, otherwise it just prints the account's name.
+
+@item A
+Inserts the full name of an account.
+
+@item W
+This is the same as @samp{%A}, except that it first displays the
+posting's state @emph{if the transaction's posting states are not
+all the same}, followed by the full account name. This is offered as
+a printing optimization, so that combined with @samp{%Y}, only the
+minimum amount of state detail is printed.
+
+@item o
+Inserts the ``optimized'' form of a posting's amount. This is
+used by the print report. In some cases, this inserts nothing; in
+others, it inserts the posting amount and its cost. It's use is
+not recommend unless you are modifying the print report.
+
+@item n
+Inserts the note associated with a posting, preceded by two spaces
+and a semi-colon, if it exists. Thus, no none becomes an empty
+string, while the note @samp{foo} is substituted as @samp{ ; foo}.
+
+@item N
+Inserts the note associated with a posting, if one exists.
+
+@item /
+The @samp{%/} construct is special. It separates a format string
+between what is printed for the first posting of a transaction, and
+what is printed for all subsequent postings. If not used, the
+same format string is used for all postings.
+@end table</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>145</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Value expressions are an expression language used by Ledger to
+calculate values used by the program for many different purposes:
+
+@enumerate
+@item
+The values displayed in reports
+@item
+For predicates (where truth is anything non-zero), to determine which
+postings are calculated (@option{-l}) or displayed (@option{-d}).
+@item
+For sorting criteria, to yield the sort key.
+@item
+In the matching criteria used by automated postings.
+@end enumerate
+
+Value expressions support most simple math and logic operators, in
+addition to a set of one letter functions and variables. A function's
+argument is whatever follows it. The following is a display predicate
+that I use with the @command{balance} command:
+
+@example
+ledger -d /^Liabilities/?T&lt;0:UT&gt;100 balance
+@end example
+
+The effect is that account totals are displayed only if: 1) A
+Liabilities account has a total less than zero; or 2) the absolute
+value of the account's total exceeds 100 units of whatever commodity
+contains. If it contains multiple commodities, only one of them must
+exceed 100 units.
+
+Display predicates are also very handy with register reports, to
+constrain which transactions are printed. For example, the following
+command shows only transactions from the beginning of the current month,
+while still calculating the running balance based on all transactions:
+
+@example
+ledger -d "d&gt;[this month]" register checking
+@end example
+
+This advantage to this command's complexity is that it prints the
+running total in terms of all transactions in the register. The following,
+simpler command is similar, but totals only the displayed
+postings:
+
+@example
+ledger -b "this month" register checking
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>146</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Below are the one letter variables available in any value expression.
+For the register and print commands, these variables relate to
+individual postings, and sometimes the account affected by a
+posting. For the balance command, these variables relate to
+accounts---often with a subtle difference in meaning. The use of each
+variable for both is specified.
+
+@table @code
+@item t
+This maps to whatever the user specified with @option{-t}. In a
+register report, @option{-t} changes the value column; in a balance
+report, it has no meaning by default. If @option{-t} was not
+specified, the current report style's value expression is used.
+
+@item T
+This maps to whatever the user specified with @option{-T}. In a
+register report, @option{-T} changes the totals column; in a balance
+report, this is the value given for each account. If @option{-T} was
+not specified, the current report style's value expression is used.
+
+@item m
+This is always the present moment/date.
+@end table</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>147</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@table @code
+@item d
+A posting's date, as the number of seconds past the epoch. This
+is always ``today'' for an account.
+
+@item a
+The posting's amount; the balance of an account, without
+considering children.
+
+@item b
+The cost of a posting; the cost of an account, without its
+children.
+
+@item v
+The market value of a posting, or an account without its children.
+
+@item g
+The net gain (market value minus cost basis), for a posting or an
+account without its children. It is the same as @samp{v-b}.
+
+@item l
+The depth (``level'') of an account. If an account has one parent,
+it's depth is one.
+
+@item n
+The index of a posting, or the count of postings affecting an
+account.
+
+@item X
+1 if a posting's transaction has been cleared, 0 otherwise.
+
+@item R
+1 if a posting is not virtual, 0 otherwise.
+
+@item Z
+1 if a posting is not automated, 0 otherwise.
+@end table</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>148</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@table @code
+@item O
+The total of all postings seen so far, or the total of an account
+and all its children.
+
+@item N
+The total count of postings affecting an account and all its
+children.
+
+@item B
+The total cost of all postings seen so far; the total cost of an
+account and all its children.
+
+@item V
+The market value of all postings seen so far, or of an account and
+all its children.
+
+@item G
+The total net gain (market value minus cost basis), for a series of
+postings, or an account and its children. It is the same as
+@samp{V-B}.
+@end table</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>149</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The available one letter functions are:
+
+@table @code
+@item -
+Negates the argument.
+
+@item U
+The absolute (unsigned) value of the argument.
+
+@item S
+Strips the commodity from the argument.
+
+@item A
+The arithmetic mean of the argument; @samp{Ax} is the same as
+@samp{x/n}.
+
+@item P
+The present market value of the argument. The syntax @samp{P(x,d)} is
+supported, which yields the market value at time @samp{d}. If no date
+is given, then the current moment is used.
+@end table</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>15</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>If you need help on how to use Ledger, or run into problems, you can
+just the Ledger mailing list at the following Web address:
+
+@example
+https://lists.sourceforge.net/lists/listinfo/ledger-discuss
+@end example
+
+You can also find help at the @samp{#ledger} channel on the IRC server
+@samp{irc.freenode.net}.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>150</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The binary and ternary operators, in order of precedence, are:
+
+@enumerate
+@item @samp{* /}
+@item @samp{+ -}
+@item @samp{! &lt; &gt; =}
+@item @samp{&amp; | ?:}
+@end enumerate</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>151</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>More complicated expressions are possible using:
+
+@table @code
+@item NUM
+A plain integer represents a commodity-less amount.
+
+@item @{AMOUNT@}
+An amount in braces can be any kind of amount supported by ledger,
+with or without a commodity. Use this for decimal values.
+
+@item /REGEXP/
+@item W/REGEXP/
+A regular expression that matches against an account's full name. If
+a posting, this will match against the account affected by the
+posting.
+
+@item //REGEXP/
+@item p/REGEXP/
+A regular expression that matches against a transaction's payee name.
+
+@item ///REGEXP/
+@item w/REGEXP/
+A regular expression that matches against an account's base name. If
+a posting, this will match against the account affected by the
+posting.
+
+@item c/REGEXP/
+A regular expression that matches against the transaction code (the text
+that occurs between parentheses before the payee name).
+
+@item e/REGEXP/
+A regular expression that matches against a posting's note, or
+comment field.
+
+@item (EXPR)
+A sub-expression is nested in parenthesis. This can be useful passing
+more complicated arguments to functions, or for overriding the natural
+precedence order of operators.
+
+@item [DATE]
+Useful specifying a date in plain terms. For example, you could say
+@samp{[2004/06/01]}.
+@end table</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>152</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The ledger file format is quite simple, but also very flexible. It
+supports many options, though typically the user can ignore most of
+them. They are summarized below.
+
+The initial character of each line determines what the line means, and
+how it should be interpreted. Allowable initial characters are:
+
+@table @code
+@item NUMBER
+A line beginning with a number denotes a transaction. It may be followed
+by any number of lines, each beginning with whitespace, to denote the
+transaction's account postings. The format of the first line is:
+
+@example
+DATE[=EDATE] [*|!] [(CODE)] DESC
+@end example
+
+If @samp{*} appears after the date (with optional effective date), it
+indicates the transaction is ``cleared'', which can mean whatever the user
+wants it t omean. If @samp{!} appears after the date, it indicates d
+the transaction is ``pending''; i.e., tentatively cleared from the user's
+point of view, but not yet actually cleared. If a @samp{CODE} appears
+in parentheses, it may be used to indicate a check number, or the type
+of the posting. Following these is the payee, or a description of
+the posting.
+
+The format of each following posting is:
+
+@example
+ ACCOUNT AMOUNT [; NOTE]
+@end example
+
+The @samp{ACCOUNT} may be surrounded by parentheses if it is a virtual
+postings, or square brackets if it is a virtual postings that
+must balance. The @samp{AMOUNT} can be followed by a per-unit
+posting cost, by specifying @samp{@@ AMOUNT}, or a complete
+posting cost with @samp{@@@@ AMOUNT}. Lastly, the @samp{NOTE} may
+specify an actual and/or effective date for the posting by using
+the syntax @samp{[ACTUAL_DATE]} or @samp{[=EFFECTIVE_DATE]} or
+@samp{[ACTUAL_DATE=EFFECtIVE_DATE]}.
+
+@item =
+An automated transaction. A value expression must appear after the equal
+sign.
+
+After this initial line there should be a set of one or more
+postings, just as if it were normal transaction. If the amounts of the
+postings have no commodity, they will be applied as modifiers to
+whichever real posting is matched by the value expression.
+
+@item ~
+A period transaction. A period expression must appear after the tilde.
+
+After this initial line there should be a set of one or more
+postings, just as if it were normal transaction.
+
+@item !
+A line beginning with an exclamation mark denotes a command directive.
+It must be immediately followed by the command word. The supported
+commands are:
+
+@table @samp
+@item !include
+Include the stated ledger file.
+
+@item !account
+The account name is given is taken to be the parent of all
+postings that follow, until @samp{!end} is seen.
+
+@item !end
+Ends an account block.
+@end table
+
+@item ;
+A line beginning with a colon indicates a comment, and is ignored.
+
+@item Y
+If a line begins with a capital Y, it denotes the year used for all
+subsequent transactions that give a date without a year. The year should
+appear immediately after the Y, for example: @samp{Y2004}. This is
+useful at the beginning of a file, to specify the year for that file.
+If all transactions specify a year, however, this command has no effect.
+
+@item P
+Specifies a historical price for a commodity. These are usually found
+in a pricing history file (see the @option{-Q} option). The syntax
+is:
+@example
+P DATE SYMBOL PRICE
+@end example
+
+@item N SYMBOL
+Indicates that pricing information is to be ignored for a given
+symbol, nor will quotes ever be downloaded for that symbol. Useful
+with a home currency, such as the dollar ($). It is recommended that
+these pricing options be set in the price database file, which
+defaults to @file{~/.pricedb}. The syntax for this command is:
+@example
+N SYMBOL
+@end example
+
+@item D AMOUNT
+Specifies the default commodity to use, by specifying an amount in the
+expected format. The @command{transaction} command will use this commodity
+as the default when none other can be determined. This command may be
+used multiple times, to set the default flags for different
+commodities; whichever is seen last is used as the default commodity.
+For example, to set US dollars as the default commodity, while also
+setting the thousands flag and decimal flag for that commodity, use:
+@example
+D $1,000.00
+@end example
+
+@item C AMOUNT1 = AMOUNT2
+Specifies a commodity conversion, where the first amount is given to
+be equivalent to the second amount. The first amount should use the
+decimal precision desired during reporting:
+@example
+C 1.00 Kb = 1024 bytes
+@end example
+
+@item i, o, b, h
+These four relate to timeclock support, which permits ledger to read
+timelog files. See the timeclock's documentation for more info on the
+syntax of its timelog files.
+@end table</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>153</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>This chapter presents a series of recipes, gradually introducing all of
+the command-line features of Ledger.
+
+For the purpose of these examples, assume the environment variable
+@var{LEDGER} is set to the file @file{sample.dat} (which is included
+in the distribution), and that the contents of that file are:
+
+@smallexample
+= /^Expenses:Books/
+ (Liabilities:Taxes) -0.10
+
+~ Monthly
+ Assets:Bank:Checking $500.00
+ Income:Salary
+
+2004/05/01 * Checking balance
+ Assets:Bank:Checking $1,000.00
+ Equity:Opening Balances
+
+2004/05/01 * Investment balance
+ Assets:Brokerage 50 AAPL @@ $30.00
+ Equity:Opening Balances
+
+2004/05/14 * Pay day
+ Assets:Bank:Checking $500.00
+ Income:Salary
+
+2004/05/27 Book Store
+ Expenses:Books $20.00
+ Liabilities:MasterCard
+
+2004/05/27 (100) Credit card company
+ Liabilities:MasterCard $20.00
+ Assets:Bank:Checking
+@end smallexample
+
+This sample file demonstrates a basic principle of accounting which it
+is recommended you follow: Keep all of your accounts under five parent
+Assets, Liabilities, Income, Expenses and Equity. It is important to
+do so in order to make sense out of the following examples.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>155</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Ledger has seven basic commands, but by far the most often used are
+@command{balance} and @command{register}. To see a summary balance of
+all accounts, use:
+
+@example
+ledger bal
+@end example
+
+@command{bal} is a short-hand for @command{balance}. This command
+prints out the summary totals of the five parent accounts used in
+@file{sample.dat}:
+
+@smallexample
+ $1,480.00
+ 50 AAPL Assets
+ $-2,500.00 Equity
+ $20.00 Expenses
+ $-500.00 Income
+ $-2.00 Liabilities
+--------------------
+ $-1,502.00
+ 50 AAPL
+@end smallexample
+
+None of the child accounts are shown, just the parent account totals.
+We can see that in @samp{Assets} there is $1,480.00, and 50 shares of
+Apple stock. There is also a negative grand total. Usually the grand
+total is zero, which means that all accounts balance@footnote{It is
+impossible for accounts not to balance in ledger; it reports an error
+if a posting does not balance}. In this case, since the 50 shares
+of Apple stock cost $1,500.00 dollars, then these two amounts balance
+each other in the grand total. The extra $2.00 comes from a virtual
+posting being added by the automatic transaction at the top of the file.
+The transaction is virtual because the account name was surrounded by
+parentheses in an automatic transaction. Automatic transactions will be
+discussed later, but first let's remove the virtual posting from
+the balance report by using the @option{--real} option:
+
+@example
+ledger --real bal
+@end example
+
+Now the report is:
+
+@smallexample
+ $1,480.00
+ 50 AAPL Assets
+ $-2,500.00 Equity
+ $20.00 Expenses
+ $-500.00 Income
+--------------------
+ $-1,500.00
+ 50 AAPL
+@end smallexample
+
+Since the liability was a virtual posting, it has dropped from the
+report and we see that final total is balanced.
+
+But we only know that it balances because @file{sample.dat} is quite
+simple, and we happen to know that the 50 shares of Apple stock cost
+$1,500.00. We can verify that things really balance by reporting the
+Apple shares in terms of their cost, instead of their quantity. To do
+this requires the @option{--basis}, or @option{-B}, option:
+
+@example
+ledger --real -B bal
+@end example
+
+This command reports:
+
+@smallexample
+ $2,980.00 Assets
+ $-2,500.00 Equity
+ $20.00 Expenses
+ $-500.00 Income
+@end smallexample
+
+With the basis cost option, the grand total has disappeared, as it is
+now zero. The confirms that the cost of everything balances to zero,
+@emph{which must always be true}. Reporting the real basis cost
+should never yield a remainder@footnote{If it ever does, then
+generated postings are involved, which can be removed using
+@option{--actual}}.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>156</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The totals reported by the balance command are only the topmost parent
+accounts. To see the totals of all child accounts as well, use the
+@option{-s} option:
+
+@example
+ledger --real -B -s bal
+@end example
+
+This reports:
+
+@smallexample
+ $2,980.00 Assets
+ $1,480.00 Bank:Checking
+ $1,500.00 Brokerage
+ $-2,500.00 Equity:Opening Balances
+ $20.00 Expenses:Books
+ $-500.00 Income:Salary
+@end smallexample
+
+This shows that the @samp{Assets} total is made up from two child
+account, but that the total for each of the other accounts comes from
+one child account.
+
+Sometimes you may have a lot of children, nested very deeply, but only
+want to report the first two levels. This can be done with a display
+predicate, using a value expression. In the value expression,
+@code{T} represents the reported total, and @code{l} is the display
+level for the account:
+
+@example
+ledger --real -B -d "T&amp;l&lt;=2" bal
+@end example
+
+This reports:
+
+@smallexample
+ $2,980.00 Assets
+ $1,480.00 Bank
+ $1,500.00 Brokerage
+ $-2,500.00 Equity:Opening Balances
+ $20.00 Expenses:Books
+ $-500.00 Income:Salary
+@end smallexample
+
+Instead of reporting @samp{Bank:Checking} as a child of @samp{Assets},
+it report only @samp{Bank}, since that account is a nesting level of
+2, while @samp{Checking} is at level 3.
+
+To review the display predicate used---@code{T&amp;l&lt;=2}---this rather
+terse expression means: Display an account only if it has a non-zero
+total (@code{T}), and its nesting level is less than or equal to 2
+(@code{l&lt;=2}).</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>157</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>While reporting the totals for all accounts can be useful, most often
+you will want to check the balance of a specific account or accounts.
+To do this, put one or more account names after the balance command.
+Since these names are really regular expressions, you can use partial
+names if you wish:
+
+@example
+ledger bal checking
+@end example
+
+Reports:
+
+@smallexample
+ $1,480.00 Assets:Bank:Checking
+@end smallexample
+
+Any number of names may be used:
+
+@example
+ledger bal checking broker liab
+@end example
+
+Reports:
+
+@smallexample
+ $1,480.00 Assets:Bank:Checking
+ 50 AAPL Assets:Brokerage
+ $-2.00 Liabilities
+@end smallexample
+
+In this case no grand total is reported, because you are asking for
+specific account balances.
+
+For those comfortable with regular expressions, any Perl regexp is
+allowed:
+
+@example
+ledger bal ^assets.*checking ^liab
+@end example
+
+Reports:
+
+@smallexample
+ $1,480.00 Assets:Bank:Checking
+ $-2.00 Liabilities:Taxes
+@end smallexample</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>158</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>While the @command{balance} command can be very handy for checking
+account totals, by far the most powerful of Ledger's reporting tools
+is the @command{register} command. In fact, internally both commands
+use the same logic, but report the results differently:
+@command{balance} shows the summary totals, while @command{register}
+reports each posting and how it contributes to that total.
+
+Paradoxically, the most basic form of @command{register} is almost
+never used, since it displays every posting:
+
+@example
+ledger reg
+@end example
+
+@command{reg} is a short-hand for @command{register}. This command
+reports:
+
+@smallexample
+2004/05/01 Checking balance Assets:Bank:Checking $1,000.00 $1,000.00
+ Equity:Opening Balan.. $-1,000.00 0
+2004/05/01 Investment balance Assets:Brokerage 50 AAPL 50 AAPL
+ Equity:Opening Balan.. $-1,500.00 $-1,500.00
+ 50 AAPL
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $-1,000.00
+ 50 AAPL
+ Income:Salary $-500.00 $-1,500.00
+ 50 AAPL
+2004/05/27 Book Store Expenses:Books $20.00 $-1,480.00
+ 50 AAPL
+ Liabilities:MasterCard $-20.00 $-1,500.00
+ 50 AAPL
+ (Liabilities:Taxes) $-2.00 $-1,502.00
+ 50 AAPL
+2004/05/27 Credit card company Liabilities:MasterCard $20.00 $-1,482.00
+ 50 AAPL
+ Assets:Bank:Checking $-20.00 $-1,502.00
+ 50 AAPL
+@end smallexample
+
+This rather verbose output shows every account posting in
+@file{sample.dat}, and how it affects the running total. The final
+total is identical to what we saw with the plain @command{balance}
+command. To see how things really balance, we can use @samp{--real
+-B}, just as we did with @command{balance}:
+
+@example
+ledger --real -B reg
+@end example
+
+Reports:
+
+@smallexample
+2004/05/01 Checking balance Assets:Bank:Checking $1,000.00 $1,000.00
+ Equity:Opening Balan.. $-1,000.00 0
+2004/05/01 Investment balance Assets:Brokerage $1,500.00 $1,500.00
+ Equity:Opening Balan.. $-1,500.00 0
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $500.00
+ Income:Salary $-500.00 0
+2004/05/27 Book Store Expenses:Books $20.00 $20.00
+ Liabilities:MasterCard $-20.00 0
+2004/05/27 Credit card company Liabilities:MasterCard $20.00 $20.00
+ Assets:Bank:Checking $-20.00 0
+@end smallexample
+
+Here we see that everything balances to zero in the end, as it must.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>159</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The most common use of the register command is to summarize
+postings based on the account(s) they affect. Using
+@file{sample.dat} as as example, we could look at all book purchases
+using:
+
+@example
+ledger reg books
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 Book Store Expenses:Books $20.00 $20.00
+@end smallexample
+
+If a double-dash (@samp{--}) occurs in the list of regular
+expressions, any following arguments are matched against payee names,
+instead of account names:
+
+@example
+ledger reg ^liab -- credit
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 Credit card company Liabilities:MasterCard $20.00 $20.00
+@end smallexample
+
+There are many reporting options for tailoring which postings are
+found, and also how to summarize the various amounts and totals that
+result. These are plumbed in greater depth below.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>16</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter Quick Reference</string>
+ <key>Title</key>
+ <string>Quick Reference</string>
+ </dict>
+ <key>160</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Although the easiest way to use the register is to report all the
+postings affecting a set of accounts, it can often result in more
+information than you want. To cope with an ever-growing amount of
+data, there are several options which can help you pinpoint your
+report to epostly the postings that interest you most. This is
+called the ``calculation'' phase of Ledger. All of its related
+options are documented under @option{--help-calc}.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>161</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@c -c, --current show only current and past transactions (not future)
+
+@option{--current}(@option{-c}) displays transactions occurring on or
+before the current date. Any transaction recorded for a future date will be
+ignored, as if it had not been seen. This is useful if you happen to
+pre-record transactions, but still wish to view your balances in terms of
+what is available today.
+
+@c -b, --begin DATE set report begin date
+@c -e, --end DATE set report end date
+
+@option{--begin DATE} (@option{-b DATE}) limits the report to only
+those transactions occurring on or after @var{DATE}. The running total in
+the register will start at zero with the first posting, even if
+there are earlier transactions.
+
+To limit the display only, but still add earlier postings to the
+running total, use the display expression @samp{-d 'd&gt;=[DATE]'}):
+
+@example
+ledger --basis -b may -d 'd&gt;=[5/14]' reg ^assets
+@end example
+
+Reports:
+
+@smallexample
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $3,000.00
+2004/05/27 Credit card company Assets:Bank:Checking $-20.00 $2,980.00
+@end smallexample
+
+In this example, the displayed postings start from @samp{5/14},
+but the calculated total starts from the beginning of @samp{may}.
+
+@option{--end DATE} (@option{-e DATE}) states when reporting should
+end, both calculation and display. The ending date is inclusive.
+
+The @var{DATE} argument to the @option{-b} and @option{-e} options can
+be rather flexible. Assuming the current date to be November 15,
+2004, then all of the following are equivalent:
+
+@example
+ledger -b oct bal
+ledger -b "this oct" bal
+ledger -b 2004/10 bal
+ledger -b 10 bal
+ledger -b last bal
+ledger -b "last month" bal
+@end example
+
+@c -p, --period STR report using the given period
+@c --period-sort EXPR sort each report period's transactions by EXPR
+
+To constrain the report to a specific time period, use
+@option{--period} (@option{-p}). A time period may have both a
+beginning and an end, or neither, as well as a specified interval.
+Here are a few examples:
+
+@example
+ledger -p 2004 bal
+ledger -p august bal
+ledger -p "from aug to oct" bal
+ledger -p "daily from 8/1 to 8/15" bal
+ledger -p "weekly since august" bal
+ledger -p "monthly from feb to oct" bal
+ledger -p "quarterly in 2004" bal
+ledger -p yearly bal
+@end example
+
+See @ref{Period expressions} for more on syntax. Also, all of the
+options @option{-b}, @option{-e} and @option{-p} may be used together,
+but whatever information occurs last takes priority. An example of
+such usage (in a script, perhaps) would be:
+
+@example
+ledger -b 2004 -e 2005 -p monthly reg ^expenses
+@end example
+
+This command is identical to:
+
+@example
+ledger -p "monthly in 2004" reg ^expenses
+@end example
+
+The postings within a period may be sorted using
+@option{--period-sort}, which takes a value expression. This is
+similar to the @option{--sort} option, except that it sorts within
+each period transaction, rather than sorting all postings in the report.
+See the documentation on @option{--sort} below for more details.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>162</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>By default, all regular postings are included in each report. To
+limit the report to certain kinds of postings, use one or more of
+the following options:
+
+@table @option
+@item -C, --cleared
+Consider only cleared postings.
+@item -U, --uncleared
+Consider only uncleared and pending postings.
+@item -R, --real
+Consider only real (non-virtual) postings.
+@item -L, --actual
+Consider only actual (non-automated) postings.
+@end table
+
+Cleared postings are indicated by an asterix placed just before
+the payee name in a posting. The meaning of this flag is up to
+the user, but typically it means that a transaction has been seen on a
+financial statement. Pending postings use an exclamation mark in
+the same position, but are mainly used only by reconciling software.
+Uncleared postings are for things like uncashed checks, credit
+charges that haven't appeared on a statement yet, etc.
+
+Real postings are all non-virtual postings, where the account
+name is not surrounded by parentheses or square brackets. Virtual
+postings are useful for showing a transfer of money that never
+really happened, like money set aside for savings without actually
+transferring it from the parent account.
+
+Actual postings are those not generated, either as part of an
+automated transaction, or a budget or forecast report. A useful of when you
+might like to filter out generated postings is with a budget:
+
+@example
+ledger --budget --actual reg ^expenses
+@end example
+
+This command outputs all postings affecting a budgeted account,
+but without subtracting the budget amount (because the generated
+postings are suppressed with @option{--actual}). The report shows
+how much you actually spent on budgeted items.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>164</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@c -r, --related calculate report using related postings
+
+Normally, a register report includes only the postings that match
+the regular expressions specified after the command word. For
+example, to report all expenses:
+
+@example
+ledger reg ^expenses
+@end example
+
+This reports:
+
+@smallexample
+2004/05/29 Book Store Expenses:Books $20.00 $20.00
+@end smallexample
+
+Using @option{--related} (@option{-r}) reports the postings that
+did not match your query, but only in transactions that otherwise would
+have matched. This has the effect of indicating where money came
+from, or when to:
+
+@example
+ledger -r reg ^expenses
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 Book Store Liabilities:MasterCard $20.00 $20.00
+@end smallexample</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>165</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@c --budget generate budget transactions based on FILE
+
+There is more information about budgeting and forecasting in
+@ref{Budgeting and forecasting}. Basically, if you have any period
+transactions in your ledger file, you can use these options. A period
+transaction looks like:
+
+@example
+~ Monthly
+ Assets:Bank:Checking $500.00
+ Income:Salary
+@end example
+
+The difference from a regular transaction is that the first line begins with
+a tilde (~), and instead of a payee there's a period expression
+(@ref{Period expressions}). Otherwise, a period transaction is in every
+other way the same as a regular transaction.
+
+With such a transaction in your ledger file, the @option{--budget} option
+will report only postings that match a budgeted account. Using
+@file{sample.dat} from above:
+
+@example
+ledger --budget reg ^income
+@end example
+
+Reports:
+
+@smallexample
+2004/05/01 Budget transaction Income:Salary $500.00 $500.00
+2004/05/14 Pay day Income:Salary $-500.00 0
+@end smallexample
+
+The final total is zero, indicating that the budget matched epostly
+for the reported period. Budgeting is most often helpful with period
+reporting; for example, to show monthly budget results use
+@option{--budget -p monthly}.
+
+@c --add-budget show all postings plus the budget
+@c --unbudgeted show only unbudgeted postings
+
+The @option{--add-budget} option reports all matching postings in
+addition to budget postings; while @option{--unbudgeted} shows
+only those that don't match a budgeted account. To summarize:
+
+@table @option
+@item --budget
+Show postings matching budgeted accounts.
+@item --unbudgeted
+Show postings matching unbudgeted accounts.
+@item --add-budget
+Show both budgeted and unbudgeted postings together (i.e., add the
+generated budget postings to the regular report).
+@end table
+
+@c --forecast EXPR generate forecast transactions while EXPR is true
+
+A report with the @option{--forecast} option will add budgeted
+postings while the specified value expression is true. For
+example:
+
+@example
+ledger --forecast 'd&lt;[2005] reg ^income
+@end example
+
+Reports:
+
+@smallexample
+2004/05/14 Pay day Income:Salary $-500.00 $-500.00
+2004/12/01 Forecast transaction Income:Salary $-500.00 $-1,000.00
+2005/01/01 Forecast transaction Income:Salary $-500.00 $-1,500.00
+@end smallexample
+
+The date this report was made was November 5, 2004; the reason the
+first forecast transaction is in december is that forecast transactions are only
+added for the future, and they only stop after the value expression
+has matched at least once, which is why the January transaction appears. A
+forecast report can be very useful for determining when money will run
+out in an account, or for projecting future cash flow:
+
+@example
+ledger --forecast 'd&lt;[2008]' -p yearly reg ^inc ^exp
+@end example
+
+This reports balances projected income against projected expenses,
+showing the resulting total in yearly intervals until 2008. For the
+case of @file{sample.dat}, which has no budgeted expenses, the result
+of the above command (in November 2004) is:
+
+@smallexample
+2004/01/01 - 2004/12/31 Income:Salary $-1,000.00 $-1,000.00
+ Expenses:Books $20.00 $-980.00
+2005/01/01 - 2005/12/31 Income:Salary $-6,000.00 $-6,980.00
+2006/01/01 - 2006/12/31 Income:Salary $-6,000.00 $-12,980.00
+2007/01/01 - 2007/12/31 Income:Salary $-6,000.00 $-18,980.00
+2008/01/01 - 2008/01/01 Income:Salary $-500.00 $-19,480.00
+@end smallexample</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>166</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@c -l, --limit EXPR calculate only postings matching EXPR
+
+Value expressions can be quite complex, and are treated more fully in
+@ref{Value expressions}. They can be used for limiting a report with
+@option{--limit} (@option{-l}). The following command report income
+since august, but expenses since october:
+
+@example
+ledger -l '(/income/&amp;d&gt;=[aug])|(/expenses/&amp;d&gt;=[oct])' reg
+@end example
+
+The basic form of this value expression is @samp{(A&amp;B)|(A&amp;B)}. The
+@samp{A} in each part matches against an account name with
+@samp{/name/}, while each @samp{B} part compares the date of the
+posting (@samp{d}) with a specified month. The resulting report
+will contain only postings which match the value expression.
+
+@c -t, --amount EXPR use EXPR to calculate the displayed amount
+@c -T, --total EXPR use EXPR to calculate the displayed total
+
+Another use of value expressions is to calculate the amount reported
+for each line of a register report, or for computing the subtotal of
+each account shown in a balance report. This example divides each
+posting amount by two:
+
+@example
+ledger -t 'a/2' reg ^exp
+@end example
+
+The @option{-t} option doesn't affect the running total, only how the
+posting amount is displayed. To change the running total, use
+@option{-T}. In that case, you will likely want to use the total
+(@samp{O}) instead of the amount (@samp{a}):
+
+@example
+ledger -T 'O/2' reg ^exp
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>168</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Even after filtering down your data to just the postings you're
+interested in, the default reporting method of one posting per
+line is often still too much. To combat this complexity, it is
+possible to ask Ledger to report the details to you in many different
+forms, summarized in various ways. This is the ``display'' phase of
+Ledger, and is documented under @option{--help-disp}.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>169</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@c -n, --collapse register: collapse transactions with multiple postings
+
+When multiple postings relate to a single transaction, they are reported
+as part of that transaction. For example, in the case of @file{sample.dat}:
+
+@example
+ledger reg -- book
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 Book Store Expenses:Books $20.00 $20.00
+ Liabilities:MasterCard $-20.00 0
+ (Liabilities:Taxes) $-2.00 $-2.00
+@end smallexample
+
+All three postings are part of one transaction, and as such the transaction
+details are printed only once. To report every transaction on a single
+line, use @option{-n} to collapse transactions with multiple postings:
+
+@example
+ledger -n reg -- book
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 Book Store &lt;Total&gt; $-2.00 $-2.00
+@end smallexample
+
+In the balance report, @option{-n} causes the grand total not to be
+displayed at the bottom of the report.
+
+@c -s, --subtotal balance: show sub-accounts; other: show subtotals
+
+If an account occurs more than once in a report, it is possible to
+combine them all and report the total per-account, using @option{-s}.
+For example, this command:
+
+@example
+ledger -B reg ^assets
+@end example
+
+Reports:
+
+@smallexample
+2004/05/01 Checking balance Assets:Bank:Checking $1,000.00 $1,000.00
+2004/05/01 Investment balance Assets:Brokerage $1,500.00 $2,500.00
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $3,000.00
+2004/05/27 Credit card company Assets:Bank:Checking $-20.00 $2,980.00
+@end smallexample
+
+But if the @option{-s} option is added, the result becomes:
+
+@smallexample
+2004/05/01 - 2004/05/29 Assets:Bank:Checking $1,480.00 $1,480.00
+ Assets:Brokerage $1,500.00 $2,980.00
+@end smallexample
+
+When account subtotaling is used, only one transaction is printed, and the
+date and name reflect the range of the combined postings.
+
+@c -P, --by-payee show summarized totals by payee
+
+With @option{-P}, postings relating to the same payee are
+combined. In this case, the date of the combined transaction is that of the
+latest posting.
+
+@c -x, --comm-as-payee set commodity name as the payee, for reporting
+
+@option{-x} changes the payee name for each posting to be the same
+as the commodity it uses. This can be especially useful combined with
+other options, like @option{-P}. For example:
+
+@example
+ledger -Px reg ^assets
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 $ Assets:Bank:Checking $1,480.00 $1,480.00
+2004/05/01 AAPL Assets:Brokerage 50 AAPL $1,480.00
+ 50 AAPL
+@end smallexample
+
+This reports shows the subtotal for each commodity held, and where it
+is located. To see the basis cost, or initial investment, add
+@option{-B}. Applied to the example above:
+
+@smallexample
+2004/05/29 $ Assets:Bank:Checking $1,480.00 $1,480.00
+2004/05/01 AAPL Assets:Brokerage $1,500.00 $2,980.00
+@end smallexample
+
+@c -E, --empty balance: show accounts with zero balance
+
+The only other options which affect summarized totals is @option{-E},
+which works only in the balance report. In this case, it shows
+matching accounts with a zero a balance, which are ordinarily
+excluded. This can be useful to see all the accounts involved in a
+report, even if some have no total.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>17</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter Ledger Tutorial</string>
+ <key>Title</key>
+ <string>Ledger Tutorial</string>
+ </dict>
+ <key>170</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Although the @option{-p} option (also @option{--period}) is much more
+versatile, there are other options to make the most common period
+reports easier:
+
+@table @option
+@item -W, --weekly
+Show weekly sub-totals. Same as @samp{-p weekly}.
+@item -M, --monthly
+Show monthly sub-totals. Same as @samp{-p monthly}.
+@item -Y, --yearly
+Show yearly sub-totals. Same as @samp{-p yearly}.
+@end table
+
+@c --dow show a days-of-the-week report
+
+There is one kind of period report cannot be done with @option{-p}.
+This is the @option{--dow}, or ``days of the week'' report, which
+shows summarized totals for each day of the week. The following
+examples shows a ``day of the week'' report of income and expenses:
+
+@example
+ledger --dow reg ^inc ^exp
+@end example
+
+Reports:
+
+@smallexample
+2004/05/27 Thursdays Expenses:Books $20.00 $20.00
+2004/05/14 Fridays Income:Salary $-500.00 $-480.00
+@end smallexample</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>171</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@c -S, --sort EXPR sort report according to the value expression EXPR
+
+The postings displayed in a report are shown in the same order as
+they appear in the ledger file. To change the order and sort a
+report, use the @option{--sort} option. @option{--sort} takes a value
+expression to determine the value to sort against, making it possible
+to sort according to complex criteria. Here are some simple and
+useful examples:
+
+@example
+ledger --sort d reg ^exp # sort by date
+ledger --sort t reg ^exp # sort by amount total
+ledger --sort -t reg ^exp # reverse sort by amount total
+ledger --sort Ut reg ^exp # sort by abs amount total
+@end example
+
+For the balance report, you will want to use @samp{T} instead of
+@samp{t}:
+
+@example
+ledger --sort T reg ^exp # sort by amount total
+ledger --sort -T reg ^exp # reverse sort by amount total
+ledger --sort UT reg ^exp # sort by abs amount total
+@end example
+
+The @option{--sort} options sorts all postings in a report. If
+periods are used (such as @option{--monthly}), this can get somewhat
+confusing. In that case, you'll probably want to sort within periods
+using @option{--period-sort} instead of @option{--sort}.
+
+@c -w, --wide for the default register report, use 132 columns
+
+And if the register seems too cramped, and you have a lot of screen
+real estate, you can use @option{-w} to format the report within 132
+acolumns, instead of 80. You are more likely then to see full payee
+and account names, as well as properly formatted totals when
+long-named commodities are used.
+
+If you want only the first or last N transactions to be printed---which can
+be very useful for viewing the last 10 transactions in your checking
+account, while also showing the cumulative balance from all
+transactions---use the @option{--head} and/or @option{--tail} options. The
+two options may be used simultaneously, for example:
+
+@example
+ledger --tail 20 reg checking
+@end example
+
+If the output from your command is very long, Ledger can output the
+data to a pager utility, such as @command{more} or @command{less}:
+
+@example
+ledger --pager /usr/bin/less reg checking
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>172</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@c -A, --average report average posting amount
+
+To see the running total changed to a running average, use
+@option{-A}. The final posting's total will be the overall
+average of all displayed postings. The works in conjunction with
+period reporting, so that you can see your monthly average expenses
+with:
+
+@example
+ledger -AM reg ^expenses:food
+ledger -AMn reg ^expenses
+@end example
+
+This works in the balance report too:
+
+@example
+ledger -AM bal ^expenses:food
+ledger -AMs bal ^expenses
+@end example
+
+@c -D, --deviation report deviation from the average
+
+The @option{-D} option changes the running average into a deviation
+from the running average. This only makes sense in the register
+report, however.
+
+@example
+ledger -DM reg ^expenses:food
+@end example
+
+@c -%, --percentage report balance totals as a percentile of the parent
+
+In the balance report only, @option{-%} changes the reported totals
+into a percentage of the parent account. This kind of report is
+confusing if negative amounts are involved, and doesn't work at all if
+multiple commodities occur in an account's history. It has a somewhat
+limited usefulness, therefore, but in certain cases it can be handy,
+such as reviewing overall expenses:
+
+@example
+ledger -%s -S T bal ^expenses
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>173</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@c --totals in the "xml" report, include running total
+
+Normally in the @command{xml} report, only posting amounts are
+printed. To include the running total under a @samp{&lt;total&gt;} tag, use
+@option{--totals}. This does not affect any other report.
+
+@c -j, --amount-data print only raw amount data (useful for scripting)
+@c -J, --total-data print only raw total data
+
+In the register report only, the output can be changed with
+@option{-j} to show only the date and the amount---without
+commodities. This only makes sense if a single commodity appears in
+the report, but can be quite useful for scripting, or passing the data
+to Gnuplot. To show only the date and running total, use @option{-J}.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>174</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@c -d, --display EXPR display only postings matching EXPR
+
+With @option{-d} you can decide which postings (or accounts in the
+balance report) are displayed, according to a value expression. The
+computed total is not affected, only the display. This can be very
+useful for shortening a report without changing the running total:
+
+@example
+ledger -d 'd&gt;=[last month]' reg checking
+@end example
+
+This command shows the checking account's register, beginning from
+last month, but with the running total reflecting the entire history
+of the account.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>175</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@c -y, --date-format STR use STR as the date format (default: %Y/%m/%d)
+
+When dates are printed in any report, the default format is
+@samp{%Y/%m/%d}, which yields dates of the form @samp{YYYY/mm/dd}.
+This can be changed with @option{-y}, whose argument is a
+@code{strftime} string---see your system's C library documentation for
+the allowable codes. Mostly you will want to use @samp{%Y}, @samp{%m}
+and @samp{%d}, in whatever combination is convenient for your locale.
+
+@c -F, --format STR use STR as the format; for each report type, use:
+@c --balance-format --register-format --print-format
+@c --plot-amount-format --plot-total-format --equity-format
+@c --prices-format --wide-register-format
+
+To change the format of the entire reported line, use @option{-F}. It
+supports quite a large number of options, which are all documented in
+@ref{Format strings}. In addition, each specific kind of report
+(except for @command{xml}) can be changed using one of the following
+options:
+
+@table @option
+@item --balance-format
+@command{balance} report. Default:
+@smallexample
+%20T %2_%-a\n
+@end smallexample
+
+@item --register-format
+@command{register} report. Default:
+@smallexample
+%D %-.20P %-.22A %12.66t %12.80T\n%/%32|%-.22A %12.66t %12.80T\n
+@end smallexample
+
+@item --print-format
+@command{print} report. Default:
+@smallexample
+%D %-.35P %-.38A %22.108t %22.132T\n%/%48|%-.38A %22.108t %22.132T\n
+@end smallexample
+
+@item --plot-amount-format
+@command{register} report when @option{-j} (plot amount) is used. Default:
+@smallexample
+%D %(St)\n
+@end smallexample
+
+@item --plot-total-format
+@command{register} report when @option{-J} (plot total) is used. Default:
+@smallexample
+%D %(ST)\n
+@end smallexample
+
+@item --equity-format
+@command{equity} report. Default:
+@smallexample
+\n%D %Y%C%P\n %-34W %12o%n\n%/ %-34W %12o%n\n
+@end smallexample
+
+@item --prices-format
+@command{prices} report. Default:
+@smallexample
+\n%D %Y%C%P\n%/ %-34W %12t\n
+@end smallexample
+
+@item --wide-register-format
+@command{register} report when @option{-w} (wide) is used. Default:
+@smallexample
+%D %-.35P %-.38A %22.108t %22.132T\n%/%48|%-.38A %22.108t %22.132T\n
+@end smallexample
+@end table</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>176</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>If your ledger file uses the standard top-level accounts: Assets,
+Liabilities, Income, Expenses, Equity: then the following queries will
+enable you to generate some typical accounting reports from your data.
+
+Your @emph{net worth} can be determined by balancing assets against
+liabilities:
+
+@example
+ledger bal ^assets ^liab
+@end example
+
+By removing long-term investment and loan accounts, you can see your
+current net liquidity (or liquid net worth):
+
+@example
+ledger bal ^assets ^liab -retirement -brokerage -loan
+@end example
+
+Balancing expenses against income yields your @emph{cash flow}, or net
+profit/loss:
+
+@example
+ledger bal ^exp ^inc
+@end example
+
+In this case, if the number is positive it means you spent more than
+you earned during the report period.
+
+@c ----------------------------------------------------------------------
+
+The most often used command is the ``balance'' command:
+
+@example
+export LEDGER=/home/johnw/doc/ledger.dat
+ledger balance
+@end example
+
+Here I've set my Ledger environment variable to point to where my
+ledger file is hiding. Thereafter, I needn't specify it again.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>177</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The balance command prints out the summarized balances of all my
+top-level accounts, excluding sub-accounts. In order to see the
+balances for a specific account, just specify a regular expression
+after the balance command:
+
+@example
+ledger balance expenses:food
+@end example
+
+This will show all the money that's been spent on food, since the
+beginning of the ledger. For food spending just this month
+(September), use:
+
+@example
+ledger -p sep balance expenses:food
+@end example
+
+Or maybe you want to see all of your assets, in which case the -s
+(show sub-accounts) option comes in handy:
+
+@example
+ledger -s balance ^assets
+@end example
+
+To exclude a particular account, use a regular expression with a
+leading minus sign. The following will show all expenses, but without
+food spending:
+
+@example
+ledger balance expenses -food
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>178</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>There is no built-in way to report posting amounts or account
+balances in terms of percentages.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>18</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter Ledger in Practice</string>
+ <key>Title</key>
+ <string>Ledger in Practice</string>
+ </dict>
+ <key>180</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Accountants will talk of ``credits'' and ``debits'', but the meaning
+is often different from the layman's understanding. To avoid
+confusion, Ledger uses only subtractions and additions, although the
+underlying intent is the same as standard accounting principles.
+
+Recall that every posting will involve two or more accounts.
+Money is transferred from one or more accounts to one or more other
+accounts. To record the posting, an amount is @emph{subtracted}
+from the source accounts, and @emph{added} to the target accounts.
+
+In order to write a Ledger transaction correctly, you must determine where
+the money comes from and where it goes to. For example, when you are
+paid a salary, you must add money to your bank account and also
+subtract it from an income account:
+
+@smallexample
+9/29 My Employer
+ Assets:Checking $500.00
+ Income:Salary $-500.00
+@end smallexample
+
+Why is the Income a negative figure? When you look at the balance
+totals for your ledger, you may be surprised to see that Expenses are
+a positive figure, and Income is a negative figure. It may take some
+getting used to, but to properly use a general ledger you must think
+in terms of how money moves. Rather than Ledger ``fixing'' the minus
+signs, let's understand why they are there.
+
+When you earn money, the money has to come from somewhere. Let's call
+that somewhere ``society''. In order for society to give you an
+income, you must take money away (withdraw) from society in order to
+put it into (make a payment to) your bank. When you then spend that
+money, it leaves your bank account (a withdrawal) and goes back to
+society (a payment). This is why Income will appear negative---it
+reflects the money you have drawn from society---and why Expenses will
+be positive---it is the amount you've given back. These additions and
+subtractions will always cancel each other out in the end, because you
+don't have the ability to create new money: it must always come from
+somewhere, and in the end must always leave. This is the beginning of
+economy, after which the explanation gets terribly difficult.
+
+Based on that explanation, here's another way to look at your balance
+report: every negative figure means that that account or person or
+place has less money now than when you started your ledger; and every
+positive figure means that that account or person or place has more
+money now that when you started your ledger. Make sense?</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>181</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Assets are money that you have, and Liabilities are money that you
+owe. ``Liabilities'' is just a more inclusive name for Debts.
+
+An Asset is typically increased by transferring money from an Income
+account, such as when you get paid. Here is a typical transaction:
+
+@smallexample
+2004/09/29 My Employer
+ Assets:Checking $500.00
+ Income:Salary
+@end smallexample
+
+Money, here, comes from an Income account belonging to ``My
+Employer'', and is transferred to your checking account. The money is
+now yours, which makes it an Asset.
+
+Liabilities track money owed to others. This can happen when you
+borrow money to buy something, or if you owe someone money. Here is
+an example of increasing a MasterCard liability by spending money with
+it:
+
+@smallexample
+2004/09/30 Restaurant
+ Expenses:Dining $25.00
+ Liabilities:MasterCard
+@end smallexample
+
+The Dining account balance now shows $25 spent on Dining, and a
+corresponding $25 owed on the MasterCard---and therefore shown as
+$-25.00. The MasterCard liability shows up as negative because it
+offsets the value of your assets.
+
+The combined total of your Assets and Liabilities is your net worth.
+So to see your current net worth, use this command:
+
+@example
+ledger balance ^assets ^liabilities
+@end example
+
+Relatedly, your Income accounts show up negative, because they
+transfer money @emph{from} an account in order to increase your
+assets. Your Expenses show up positive because that is where the
+money went to. The combined total of Income and Expenses is your cash
+flow. A positive cash flow means you are spending more than you make,
+since income is always a negative figure. To see your current cash
+flow, use this command:
+
+@example
+ledger balance ^income ^expenses
+@end example
+
+Another common question to ask of your expenses is: How much do I
+spend each month on X? Ledger provides a simple way of displaying
+monthly totals for any account. Here is an example that summarizes
+your monthly automobile expenses:
+
+@example
+ledger -M register expenses:auto
+@end example
+
+This assumes, of course, that you use account names like
+@samp{Expenses:Auto:Gas} and @samp{Expenses:Auto:Repair}.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>182</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Sometimes you will want to spend money on behalf of someone else,
+which will eventually get repaid. Since the money is still ``yours'',
+it is really an asset. And since the expenditure was for someone
+else, you don't want it contaminating your Expenses reports. You will
+need to keep an account for tracking reimbursements.
+
+This is fairly easy to do in ledger. When spending the money, spend
+it @emph{to} your Assets:Reimbursements, using a different account for
+each person or business that you spend money for. For example:
+
+@smallexample
+2004/09/29 Circuit City
+ Assets:Reimbursements:Company XYZ $100.00
+ Liabilities:MasterCard
+@end smallexample
+
+This shows $100.00 spent on a MasterCard at Circuit City, with the
+expense was made on behalf of Company XYZ. Later, when Company XYZ
+pays the amount back, the money will transfer from that reimbursement
+account back to a regular asset account:
+
+@smallexample
+2004/09/29 Company XYZ
+ Assets:Checking $100.00
+ Assets:Reimbursements:Company XYZ
+@end smallexample
+
+This deposits the money owed from Company XYZ into a checking account,
+presumably because they paid the amount back with a check.
+
+But what to do if you run your own business, and you want to keep
+track of expenses made on your own behalf, while still tracking
+everything in a single ledger file? This is more complex, because you
+need to track two separate things: 1) The fact that the money should
+be reimbursed to you, and 2) What the expense account was, so that you
+can later determine where your company is spending its money.
+
+This kind of posting is best handled with mirrored postings in
+two different files, one for your personal accounts, and one for your
+company accounts. But keeping them in one file involves the same
+kinds of postings, so those are what is shown here. First, the
+personal transaction, which shows the need for reimbursement:
+
+@smallexample
+2004/09/29 Circuit City
+ Assets:Reimbursements:Company XYZ $100.00
+ Liabilities:MasterCard
+@end smallexample
+
+This is the same as above, except that you own Company XYZ, and are
+keeping track of its expenses in the same ledger file. This transaction
+should be immediately followed by an equivalent transaction, which shows the
+kind of expense, and also notes the fact that $100.00 is now payable
+to you:
+
+@smallexample
+2004/09/29 Circuit City
+ Company XYZ:Expenses:Computer:Software $100.00
+ Company XYZ:Accounts Payable:Your Name
+@end smallexample
+
+This second transaction shows that Company XYZ has just spent $100.00 on
+software, and that this $100.00 came from Your Name, which must be
+paid back.
+
+These two transactions can also be merged, to make things a little clearer.
+Note that all amounts must be specified now:
+
+@smallexample
+2004/09/29 Circuit City
+ Assets:Reimbursements:Company XYZ $100.00
+ Liabilities:MasterCard $-100.00
+ Company XYZ:Expenses:Computer:Software $100.00
+ Company XYZ:Accounts Payable:Your Name $-100.00
+@end smallexample
+
+To ``pay back'' the reimbursement, just reverse the order of
+everything, except this time drawing the money from a company asset,
+paying it to accounts payable, and then drawing it again from the
+reimbursement account, and paying it to your personal asset account.
+It's easier shown than said:
+
+@smallexample
+2004/10/15 Company XYZ
+ Assets:Checking $100.00
+ Assets:Reimbursements:Company XYZ $-100.00
+ Company XYZ:Accounts Payable:Your Name $100.00
+ Company XYZ:Assets:Checking $-100.00
+@end smallexample
+
+And now the reimbursements account is paid off, accounts payable is
+paid off, and $100.00 has been effectively transferred from the
+company's checking account to your personal checking account. The
+money simply ``waited''---in both @samp{Assets:Reimbursements:Company
+XYZ}, and @samp{Company XYZ:Accounts Payable:Your Name}---until such
+time as it could be paid off.
+
+The value of tracking expenses from both sides like that is that you
+do not contaminate your personal expense report with expenses made on
+behalf of others, while at the same time making it possible to
+generate accurate reports of your company's expenditures. It is more
+verbose than just paying for things with your personal assets, but it
+gives you a very accurate information trail.
+
+The advantage to keep these doubled transactions together is that they
+always stay in sync. The advantage to keeping them apart is that it
+clarifies the transfer's point of view. To keep the postings in
+separate files, just separate the two transactions that were joined above.
+For example, for both the expense and the pay-back shown above, the
+following four transactions would be created. Two in your personal ledger
+file:
+
+@smallexample
+2004/09/29 Circuit City
+ Assets:Reimbursements:Company XYZ $100.00
+ Liabilities:MasterCard $-100.00
+
+2004/10/15 Company XYZ
+ Assets:Checking $100.00
+ Assets:Reimbursements:Company XYZ $-100.00
+@end smallexample
+
+And two in your company ledger file:
+
+@smallexample
+!account Company XYZ
+
+2004/09/29 Circuit City
+ Expenses:Computer:Software $100.00
+ Accounts Payable:Your Name $-100.00
+
+2004/10/15 Company XYZ
+ Accounts Payable:Your Name $100.00
+ Assets:Checking $-100.00
+
+!end
+@end smallexample
+
+(Note: The @samp{!account} above means that all accounts mentioned in
+the file are children of that account. In this case it means that all
+activity in the file relates to Company XYZ).
+
+After creating these transactions, you will always know that $100.00 was
+spent using your MasterCard on behalf of Company XYZ, and that Company
+XYZ spent the money on computer software and paid it back about two
+weeks later.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>183</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>A query such as the following shows all expenses since last
+October, sorted by total:
+
+@example
+ledger -b "last oct" -s -S T bal ^expenses
+@end example
+
+From left to right the options mean: Show transactions since October, 2003;
+show all sub-accounts; sort by the absolute value of the total; and
+report the balance for all expenses.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>184</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The following query makes it easy to see monthly expenses, with each
+month's expenses sorted by the amount:
+
+@example
+ledger -M --period-sort t reg ^expenses
+@end example
+
+Now, you might wonder where the money came from to pay for these
+things. To see that report, add @option{-r}, which shows the
+``related account'' postings:
+
+@example
+ledger -M --period-sort t -r reg ^expenses
+@end example
+
+But maybe this prints too much information. You might just want to
+see how much you're spending with your MasterCard. That kind of query
+requires the use of a display predicate, since the postings
+calculated must match @samp{^expenses}, while the postings
+displayed must match @samp{mastercard}. The command would be:
+
+@example
+ledger -M -r -d /mastercard/ reg ^expenses
+@end example
+
+This query says: Report monthly subtotals; report the ``related
+account'' postings; display only related postings whose
+account matches @samp{mastercard}, and base the calculation on
+postings matching @samp{^expenses}.
+
+This works just as well for report the overall total, too:
+
+@example
+ledger -s -r -d /mastercard/ reg ^expenses
+@end example
+
+The @option{-s} option subtotals all postings, just as @option{-M}
+subtotaled by the month. The running total in both cases is off,
+however, since a display expression is being used.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>185</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Here are some useful plots:
+
+@smallexample
+report -j -M reg ^expenses # monthly expenses
+report -J reg checking # checking account balance
+report -J reg ^income ^expenses # cash flow report
+
+# net worth report, ignoring non-$ postings
+
+report -J -l "Ua&gt;=@{\$0.01@}" reg ^assets ^liab
+
+# net worth report starting last February. the use of a display
+# predicate (-d) is needed, otherwise the balance will start at
+# zero, and thus the y-axis will not reflect the true balance
+
+report -J -l "Ua&gt;=@{\$0.01@}" -d "d&gt;=[last feb]" reg ^assets ^liab
+@end smallexample
+
+The last report uses both a calculation predicate (@option{-l}) and a
+display predicate (@option{-d}). The calculation predicates limits
+the report to postings whose amount is greater than $1 (which can
+only happen if the posting amount is in dollars). The display
+predicate limits the transactions @emph{displayed} to just those since last
+February, even those transactions from before then will be computed as part
+of the balance.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>186</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>If you have @command{Gnuplot} installed, you can graph any of the
+above register reports. The script to do this is included in the
+ledger distribution, and is named @file{scripts/report}. Install
+@file{report} anywhere along your @env{PATH}, and then use
+@command{report} instead of @command{ledger} when doing a register
+report. The only thing to keep in mind is that you must specify
+@option{-j} or @option{-J} to indicate whether Gnuplot should plot the
+amount, or the running total. For example, this command plots total
+monthly expenses made on your MasterCard.
+
+@example
+report -j -M -r -d /mastercard/ reg ^expenses
+@end example
+
+The @command{report} script is a very simple Bourne shell script, that
+passes a set of scripted commands to Gnuplot. Feel free to modify the
+script to your liking, since you may prefer histograms to line plots,
+for example.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>188</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Keeping a budget allows you to pay closer attention to your income and
+expenses, by reporting how far your actual financial activity is from
+your expectations.
+
+To start keeping a budget, put some period transactions at the top of your
+ledger file. A period transaction is almost identical to a regular transaction,
+except that it begins with a tilde and has a period expression in
+place of a payee. For example:
+
+@smallexample
+~ Monthly
+ Expenses:Rent $500.00
+ Expenses:Food $450.00
+ Expenses:Auto:Gas $120.00
+ Expenses:Insurance $150.00
+ Expenses:Phone $125.00
+ Expenses:Utilities $100.00
+ Expenses:Movies $50.00
+ Expenses $200.00 ; all other expenses
+ Assets
+
+~ Yearly
+ Expenses:Auto:Repair $500.00
+ Assets
+@end smallexample
+
+These two period transactions give the usual monthly expenses, as well as
+one typical yearly expense. For help on finding out what your average
+monthly expense is for any category, use a command like:
+
+@example
+ledger -p "this year" -MAs bal ^expenses
+@end example
+
+The reported totals are the current year's average for each account.
+
+Once these period transactions are defined, creating a budget report is as
+easy as adding @option{--budget} to the command-line. For example, a
+typical monthly expense report would be:
+
+@example
+ledger -M reg ^exp
+@end example
+
+To see the same report balanced against your budget, use:
+
+@example
+ledger --budget -M reg ^exp
+@end example
+
+A budget report includes only those accounts that appear in the
+budget. To see all expenses balanced against the budget, use
+@option{--add-budget}. You can even see only the unbudgeted expenses
+using @option{--unbudgeted}:
+
+@example
+ledger --unbudgeted -M reg ^exp
+@end example
+
+You can also use these flags with the @command{balance} command.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>189</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Sometimes it's useful to know what your finances will look like in the
+future, such as determining when an account will reach zero. Ledger
+makes this easy to do, using the same period transactions as are used for
+budgeting. An example forecast report can be generated with:
+
+@example
+ledger --forecast "T&gt;@{\$-500.00@}" register ^assets ^liabilities
+@end example
+
+This report continues outputting postings until the running total
+is greater than $-500.00. A final posting is always output, to
+show you what the total afterwards would be.
+
+Forecasting can also be used with the balance report, but by date
+only, and not against the running total:
+
+@example
+ledger --forecast "d&lt;[2010]" bal ^assets ^liabilities
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>19</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter Random things</string>
+ <key>Title</key>
+ <string>Random things</string>
+ </dict>
+ <key>190</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Ledger makes no assumptions about the commodities you use; it only
+requires that you specify a commodity. The commodity may be any
+non-numeric string that does not contain a period, comma, forward
+slash or at-sign. It may appear before or after the amount, although
+it is assumed that symbols appearing before the amount refer to
+currencies, while non-joined symbols appearing after the amount refer
+to commodities. Here are some valid currency and commodity
+specifiers:
+
+@example
+$20.00 ; currency: twenty US dollars
+40 AAPL ; commodity: 40 shares of Apple stock
+60 DM ; currency: 60 Deutsch Mark
+£50 ; currency: 50 British pounds
+50 EUR ; currency: 50 Euros (or use appropriate symbol)
+@end example
+
+Ledger will examine the first use of any commodity to determine how
+that commodity should be printed on reports. It pays attention to
+whether the name of commodity was separated from the amount, whether
+it came before or after, the precision used in specifying the amount,
+whether thousand marks were used, etc. This is done so that printing
+the commodity looks the same as the way you use it.
+
+An account may contain multiple commodities, in which case it will
+have separate totals for each. For example, if your brokerage account
+contains both cash, gold, and several stock quantities, the balance
+might look like:
+
+@smallexample
+ $200.00
+100.00 AU
+ AAPL 40
+ BORL 100
+ FEQTX 50 Assets:Brokerage
+@end smallexample
+
+This balance report shows how much of each commodity is in your
+brokerage account.
+
+Sometimes, you will want to know the current street value of your
+balance, and not the commodity totals. For this to happen, you must
+specify what the current price is for each commodity. The price can
+be any commodity, in which case the balance will be computed in terms
+of that commodity. The usual way to specify prices is with a price
+history file, which might look like this:
+
+@smallexample
+P 2004/06/21 02:18:01 FEQTX $22.49
+P 2004/06/21 02:18:01 BORL $6.20
+P 2004/06/21 02:18:02 AAPL $32.91
+P 2004/06/21 02:18:02 AU $400.00
+@end smallexample
+
+Specify the price history to use with the @option{--price-db} option,
+with the @option{-V} option to report in terms of current market
+value:
+
+@example
+ledger --price-db prices.db -V balance brokerage
+@end example
+
+The balance for your brokerage account will be reported in US dollars,
+since the prices database uses that currency.
+
+@smallexample
+$40880.00 Assets:Brokerage
+@end smallexample
+
+You can convert from any commodity to any other commodity. Let's say
+you had $5000 in your checking account, and for whatever reason you
+wanted to know many ounces of gold that would buy, in terms of the
+current price of gold:
+
+@example
+ledger -T "@{1 AU@}*(O/P@{1 AU@})" balance checking
+@end example
+
+Although the total expression appears complex, it is simply saying
+that the reported total should be in multiples of AU units, where the
+quantity is the account total divided by the price of one AU. Without
+the initial multiplication, the reported total would still use the
+dollars commodity, since multiplying or dividing amounts always keeps
+the left value's commodity. The result of this command might be:
+
+@smallexample
+14.01 AU Assets:Checking
+@end smallexample</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>191</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Whenever a commodity is purchased using a different commodity (such as
+a share of common stock using dollars), it establishes a price for
+that commodity on that day. It is also possible, by recording price
+details in a ledger file, to specify other prices for commodities at
+any given time. Such price transactions might look like those below:
+
+@smallexample
+P 2004/06/21 02:17:58 TWCUX $27.76
+P 2004/06/21 02:17:59 AGTHX $25.41
+P 2004/06/21 02:18:00 OPTFX $39.31
+P 2004/06/21 02:18:01 FEQTX $22.49
+P 2004/06/21 02:18:02 AAPL $32.91
+@end smallexample
+
+By default, ledger will not consider commodity prices when generating
+its various reports. It will always report balances in terms of the
+commodity total, rather than the current value of those commodities.
+To enable pricing reports, use one of the commodity reporting options.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>192</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Sometimes a commodity has several forms which are all equivalent. An
+example of this is time. Whether tracked in terms of minutes, hours
+or days, it should be possible to convert between the various forms.
+Doing this requires the use of commodity equivalencies.
+
+For example, you might have the following two postings, one which
+transfers an hour of time into a @samp{Billable} account, and another
+which decreases the same account by ten minutes. The resulting report
+will indicate that fifty minutes remain:
+
+@smallexample
+2005/10/01 Work done for company
+ Billable:Client 1h
+ Project:XYZ
+
+2005/10/02 Return ten minutes to the project
+ Project:XYZ 10m
+ Billable:Client
+@end smallexample
+
+Reporting the balance for this ledger file produces:
+
+@smallexample
+ 50.0m Billable:Client
+ -50.0m Project:XYZ
+@end smallexample
+
+This example works because ledger already knows how to handle seconds,
+minutes and hours, as part of its time tracking support. Defining
+other equivalencies is simple. The following is an example that
+creates data equivalencies, helpful for tracking bytes, kilobytes,
+megabytes, and more:
+
+@smallexample
+C 1.00 Kb = 1024 b
+C 1.00 Mb = 1024 Kb
+C 1.00 Gb = 1024 Mb
+C 1.00 Tb = 1024 Gb
+@end smallexample
+
+Each of these definitions correlates a commodity (such as @samp{Kb})
+and a default precision, with a certain quantity of another commodity.
+In the above example, kilobytes are reporetd with two decimal places
+of precision and each kilobyte is equal to 1024 bytes.
+
+Equivalency chains can be as long as desired. Whenever a commodity
+would report as a decimal amount (less than @samp{1.00}), the next
+smallest commodity is used. If a commodity could be reported in terms
+of a higher commodity without resulting to a partial fraction, then
+the larger commodity is used.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>193</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Since Ledger's accounts and commodity system is so flexible, you can
+have accounts that don't really exist, and use commodities that no one
+else recognizes. For example, let's say you are buying and selling
+various items in EverQuest, and want to keep track of them using a
+ledger. Just add items of whatever quantity you wish into your
+EverQuest account:
+
+@smallexample
+9/29 Get some stuff at the Inn
+ Places:Black's Tavern -3 Apples
+ Places:Black's Tavern -5 Steaks
+ EverQuest:Inventory
+@end smallexample
+
+Now your EverQuest:Inventory has 3 apples and 5 steaks in it. The
+amounts are negative, because you are taking @emph{from} Black's
+Tavern in order to add to your Inventory account. Note that you don't
+have to use @samp{Places:Black's Tavern} as the source account. You
+could use @samp{EverQuest:System} to represent the fact that you
+acquired them online. The only purpose for choosing one kind of
+source account over another is for generate more informative reports
+later on. The more you know, the better analysis you can perform.
+
+If you later sell some of these items to another player, the transaction
+would look like:
+
+@smallexample
+10/2 Sturm Brightblade
+ EverQuest:Inventory -2 Steaks
+ EverQuest:Inventory 15 Gold
+@end smallexample
+
+Now you've turned 2 steaks into 15 gold, courtesy of your customer,
+Sturm Brightblade.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>194</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The most confusing transaction in any ledger will be your equity account---
+because starting balances can't come out of nowhere.
+
+When you first start your ledger, you will likely already have money
+in some of your accounts. Let's say there's $100 in your checking
+account; then add a transaction to your ledger to reflect this amount.
+Where will money come from? The answer: your equity.
+
+@smallexample
+10/2 Opening Balance
+ Assets:Checking $100.00
+ Equity:Opening Balances
+@end smallexample
+
+But what is equity? You may have heard of equity when people talked
+about house mortgages, as ``the part of the house that you own''.
+Basically, equity is like the value of something. If you own a car
+worth $5000, then you have $5000 in equity in that car. In order to
+turn that car (a commodity) into a cash flow, or a credit to your bank
+account, you will have to debit the equity by selling it.
+
+When you start a ledger, you are probably already worth something.
+Your net worth is your current equity. By transferring the money in
+the ledger from your equity to your bank accounts, you are crediting
+the ledger account based on your prior equity. That is why, when you
+look at the balance report, you will see a large negative number for
+Equity that never changes: Because that is what you were worth (what
+you debited from yourself in order to start the ledger) before the
+money started moving around. If the total positive value of your
+assets is greater than the absolute value of your starting equity, it
+means you are making money.
+
+Clear as mud? Keep thinking about it. Until you figure it out, put
+@samp{-Equity} at the end of your balance command, to remove the
+confusing figure from the total.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>195</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Something that stops many people from keeping a ledger at all is the
+insanity of tracking small cash expenses. They rarely generate a
+receipt, and there are often a lot of small postings, rather than
+a few large ones, as with checks.
+
+One solution is: don't bother. Move your spending to a debit card,
+but in general ignore cash. Once you withdraw it from the ATM, mark
+it as already spent to an @samp{Expenses:Cash} category:
+
+@smallexample
+2004/03/15 ATM
+ Expenses:Cash $100.00
+ Assets:Checking
+@end smallexample
+
+If at some point you make a large cash expense that you want to track,
+just ``move'' the amount of the expense from @samp{Expenses:Cash} into
+the target account:
+
+@smallexample
+2004/03/20 Somebody
+ Expenses:Food $65.00
+ Expenses:Cash
+@end smallexample
+
+This way, you can still track large cash expenses, while ignoring all
+of the smaller ones.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>196</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>There are situations when the accounts you're tracking are different
+between your clients and the financial institutions where money is
+kept. An example of this is working as the treasurer for a religious
+institution. From the secular point of view, you might be working
+with three different accounts:
+
+@itemize
+@item Checking
+@item Savings
+@item Credit Card
+@end itemize
+
+From a religious point of view, the community expects to divide its
+resources into multiple ``funds'', from which it makes purchases or
+reserves resources for later:
+
+@itemize
+@item School fund
+@item Building fund
+@item Community fund
+@end itemize
+
+The problem with this kind of setup is that when you spend money, it
+comes from two or more places at once: the account and the fund. And
+yet, the correlation of amounts between funds and accounts is rarely
+one-to-one. What if the school fund has @samp{$500.00}, but
+@samp{$400.00} of that comes from Checking, and @samp{$100.00} from
+Savings?
+
+Traditional finance packages require that the money reside in only one
+place. But there are really two ``views'' of the data: from the
+account point of view and from the fund point of view -- yet both sets
+should reflect the same overall expenses and cash flow. It's simply
+where the money resides that differs.
+
+This situation can be handled one of two ways. The first is using
+virtual postings to represent the fact that money is moving to and
+from two kind of accounts at the same time:
+
+@smallexample
+2004/03/20 Contributions
+ Assets:Checking $500.00
+ Income:Donations
+
+2004/03/25 Distribution of donations
+ [Funds:School] $300.00
+ [Funds:Building] $200.00
+ [Assets:Checking] $-500.00
+@end smallexample
+
+The use of square brackets in the second transaction ensures that the
+virtual postings balance to zero. Now money can be spent directly
+from a fund at the same time as money is drawn from a physical
+account:
+
+@smallexample
+2004/03/25 Payment for books (paid from Checking)
+ Expenses:Books $100.00
+ Assets:Checking $-100.00
+ (Funds:School) $-100.00
+@end smallexample
+
+When reports are generated, by default they'll appear in terms of the
+funds. In this case, you will likely want to mask out your
+@samp{Assets} account, because otherwise the balance won't make much
+sense:
+
+@example
+ledger bal -^Assets
+@end example
+
+If the @option{--real} option is used, the report will be in terms of
+the real accounts:
+
+@example
+ledger --real bal
+@end example
+
+If more asset accounts are needed as the source of a posting, just
+list them as you would normally, for example:
+
+@smallexample
+2004/03/25 Payment for books (paid from Checking)
+ Expenses:Books $100.00
+ Assets:Checking $-50.00
+ Liabilities:Credit Card $-50.00
+ (Funds:School) $-100.00
+@end smallexample
+
+The second way of tracking funds is to use transaction codes. In this
+respect the codes become like virtual accounts that embrace the entire
+set of postings. Basically, we are associating a transaction with a
+fund by setting its code. Here are two transactions that desposit money
+into, and spend money from, the @samp{Funds:School} fund:
+
+@smallexample
+2004/03/25 (Funds:School) Donations
+ Assets:Checking $100.00
+ Income:Donations
+
+2004/04/25 (Funds:School) Payment for books
+ Expenses:Books $50.00
+ Assets:Checking
+@end smallexample
+
+Note how the accounts now relate only to the real accounts, and any
+balance or registers reports will reflect this. That the transactions
+relate to a particular fund is kept only in the code.
+
+How does this become a fund report? By using the
+@option{--code-as-payee} option, you can generate a register report
+where the payee for each posting shows the code. Alone, this is
+not terribly interesting; but when combined with the
+@option{--by-payee} option, you will now see account subtotals for any
+postings related to a specific fund. So, to see the current
+monetary balances of all funds, the command would be:
+
+@smallexample
+ledger --code-as-payee -P reg ^Assets
+@end smallexample
+
+Or to see a particular funds expenses, the @samp{School} fund in this
+case:
+
+@smallexample
+ledger --code-as-payee -P reg ^Expenses -- School
+@end smallexample
+
+Both approaches yield different kinds of flexibility, depending on how
+you prefer to think of your funds: as virtual accounts, or as tags
+associated with particular transactions. Your own tastes will decide which
+is best for your situation.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>197</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>After a while, your ledger can get to be pretty large. While this
+will not slow down the ledger program much---it's designed to process
+ledger files very quickly---things can start to feel ``messy''; and
+it's a universal complaint that when finances feel messy, people avoid
+them.
+
+Thus, archiving the data from previous years into their own files can
+offer a sense of completion, and freedom from the past. But how to
+best accomplish this with the ledger program? There are two commands
+that make it very simple: @command{print}, and @command{equity}.
+
+Let's take an example file, with data ranging from year 2000 until
+2004. We want to archive years 2000 and 2001 to their own file,
+leaving just 2003 and 2004 in the current file. So, use
+@command{print} to output all the earlier transactions to a file called
+@file{ledger-old.dat}:
+
+@smallexample
+ledger -f ledger.dat -b 2000 -e 2001 print &gt; ledger-old.dat
+@end smallexample
+
+To delete older data from the current ledger file, use @command{print}
+again, this time specifying year 2002 as the starting date:
+
+@example
+ledger -f ledger.dat -b 2002 print &gt; x
+mv x ledger.dat
+@end example
+
+However, now the current file contains @emph{only} postings from
+2002 onward, which will not yield accurate present-day balances,
+because the net income from previous years is no longer being tallied.
+To compensate for this, we must append an equity report for the old
+ledger at the beginning of the new one:
+
+@example
+ledger -f ledger-old.dat equity &gt; equity.dat
+cat equity.dat ledger.dat &gt; x
+mv x ledger.dat
+rm equity.dat
+@end example
+
+Now the balances reported from @file{ledger.dat} are identical to what
+they were before the data was split.
+
+How often should you split your ledger? You never need to, if you
+don't want to. Even eighty years of data will not slow down ledger
+much---and that's just using present day hardware! Or, you can keep
+the previous and current year in one file, and each year before that
+in its own file. It's really up to you, and how you want to organize
+your finances. For those who also keep an accurate paper trail, it
+might be useful to archive the older years to their own files, then
+burn those files to a CD to keep with the paper records---along with
+any electronic statements received during the year. In the arena of
+organization, just keep in mind this maxim: Do whatever keeps you
+doing it.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>198</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>A virtual posting is when you, in your mind, see money as moving
+to a certain place, when in reality that money has not moved at all.
+There are several scenarios in which this type of tracking comes in
+handy, and each of them will be discussed in detail.
+
+To enter a virtual posting, surround the account name in
+parentheses. This form of usage does not need to balance. However,
+if you want to ensure the virtual posting balances with other
+virtual postings in the same transaction, use square brackets. For
+example:
+
+@smallexample
+10/2 Paycheck
+ Assets:Checking $1000.00
+ Income:Salary $-1000.00
+ (Debt:Alimony) $200.00
+@end smallexample
+
+In this example, after receiving a paycheck an alimony debt is
+increased---even though no money has moved around yet.
+
+@smallexample
+10/2 Paycheck
+ Assets:Checking $1000.00
+ Income:Salary $-1000.00
+ [Savings:Trip] $200.00
+ [Assets:Checking] $-200.00
+@end smallexample
+
+In this example, $200 has been deducted from checking toward savings
+for a trip. It will appear as though the money has been moved from
+the account into @samp{Savings:Trip}, although no money has actually
+moved anywhere.
+
+When balances are displayed, virtual postings will be factored in.
+To view balances without any virtual balances factored in, using the
+@option{-R} flag, for ``reality''.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>199</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>As a Bahá'í, I need to compute Huqúqu'lláh whenever I acquire assets.
+It is similar to tithing for Jews and Christians, or to Zakát for
+Muslims. The epost details of computing Huqúqu'lláh are somewhat
+complex, but if you have further interest, please consult the Web.
+
+Ledger makes this otherwise difficult law very easy. Just set up an
+automated posting at the top of your ledger file:
+
+@smallexample
+; This automated transaction will compute Huqúqu'lláh based on this
+; journal's postings. Any that match will affect the
+; Liabilities:Huququ'llah account by 19% of the value of that
+; posting.
+
+= /^(?:Income:|Expenses:(?:Business|Rent$|Furnishings|Taxes|Insurance))/
+ (Liabilities:Huququ'llah) 0.19
+@end smallexample
+
+This automated posting works by looking at each posting in the
+ledger file. If any match the given value expression, 19% of the
+posting's value is applied to the @samp{Liabilities:Huququ'llah}
+account. So, if $1000 is earned from @samp{Income:Salary}, $190 is
+added to @samp{Liabilities:Huqúqu'lláh}; if $1000 is spent on Rent,
+$190 is subtracted. The ultimate balance of Huqúqu'lláh reflects how
+much is owed in order to fulfill one's obligation to Huqúqu'lláh.
+When ready to pay, just write a check to cover the amount shown in
+@samp{Liabilities:Huququ'llah}. That transaction would look like:
+
+@smallexample
+2003/01/01 (101) Baha'i Huqúqu'lláh Trust
+ Liabilities:Huququ'llah $1,000.00
+ Assets:Checking
+@end smallexample
+
+That's it. To see how much Huqúq is currently owed based on your
+ledger transactions, use:
+
+@example
+ledger balance Liabilities:Huquq
+@end example
+
+This works fine, but omits one aspect of the law: that Huquq is only
+due once the liability exceeds the value of 19 mithqáls of gold (which
+is roughly 2.22 ounces). So what we want is for the liability to
+appear in the balance report only when it exceeds the present day
+value of 2.22 ounces of gold. This can be accomplished using the
+command:
+
+@smallexample
+ledger -Q -t "/Liab.*Huquq/?(a/P@{2.22 AU@}&lt;=@{-1.0@}&amp;a):a" -s bal liab
+@end smallexample
+
+With this command, the current price for gold is downloaded, and the
+Huqúqu'lláh is reported only if its value exceeds that of 2.22 ounces
+of gold. If you wish the liability to be reflected in the parent
+subtotal either way, use this instead:
+
+@smallexample
+ledger -Q -T "/Liab.*Huquq/?(O/P@{2.22 AU@}&lt;=@{-1.0@}&amp;O):O" -s bal liab
+@end smallexample
+
+In some cases, you may wish to refer to the account of whichever
+posting matched your automated transaction's value expression. To do
+this, use the special account name @samp{$account}:
+
+@smallexample
+= /^Some:Long:Account:Name/
+ [$account] -0.10
+ [Savings] 0.10
+@end smallexample
+
+This example causes 10% of the matching account's total to be deferred
+to the @samp{Savings} account---as a balanced virtual posting,
+which may be excluded from reports by using @option{--real}.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>20</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter Anatomy of a journal file</string>
+ <key>Title</key>
+ <string>Anatomy of a journal file</string>
+ </dict>
+ <key>200</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>In the Ledger tarball is an Emacs module, @file{ledger.el}. This
+module makes the process of keeping a text ledger much easier for
+Emacs users. I recommend putting this at the top of your ledger file:
+
+@example
+; -*-ledger-*-
+@end example
+
+And this in your @file{.emacs} file, after copying @file{ledger.el} to
+your @file{site-lisp} directory:
+
+@example
+(load "ledger")
+@end example
+
+Now when you edit your ledger file, it will be in
+@command{ledger-mode}. @command{ledger-mode} adds these commands:
+
+@table @strong
+@item C-c C-a
+For quickly adding new transactions based on the form of older ones (see
+previous section).
+
+@item C-c C-c
+Toggles the ``cleared'' flag of the posting under point.
+
+@item C-c C-d
+Delete the transaction under point.
+
+@item C-c C-r
+Reconciles an account by displaying the postings in another
+buffer, where simply hitting the spacebar will toggle the pending flag
+of the posting in the ledger. Once all the appropriate
+postings have been marked, press C-c C-c in the reconcile buffer
+to ``commit'' the reconciliation, which will mark all of the transactions
+as cleared, and display the new cleared balance in the minibuffer.
+
+@item C-c C-m
+Set the default month for new transactions added with C-c C-a. This is
+handy if you have a large number of postings to enter from a
+previous month.
+
+@item C-c C-y
+Set the default year for new transactions added with C-c C-a. This is
+handy if you have a large number of postings to enter from a
+previous year.
+@end table
+
+Once you enter the reconcile buffer, there are several key commands
+available:
+
+@table @strong
+@item RET
+Visit the ledger file transaction corresponding to the reconcile transaction.
+
+@item C-c C-c
+Commit the reconcialation. This marks all of the marked postings
+as ``cleared'', saves the ledger file, and then displays the new
+cleared balance.
+
+@item C-l
+Refresh the reconcile buffer by re-reading postings from the
+ledger data file.
+
+@item SPC
+Toggle the posting under point as cleared.
+
+@item a
+Add a new transaction to the ledger data file, and refresh the reconcile
+buffer to include its postings (if the transaction is added to the same
+account as the one being reconciled).
+
+@item d
+Delete the transaction related to the posting under point. Note: This
+may result in multiple postings being deleted.
+
+@item n
+Move to the next line.
+
+@item p
+Move to the previous line.
+
+@item C-c C-r
+@item r
+Attempt to auto-reconcile the postings to the entered balance. If
+it can do so, it will mark all those postings as pending that
+would yield the specified balance.
+
+@item C-x C-s
+@item s
+Save the ledger data file, and show the current cleared balance for
+the account being reconciled.
+
+@item q
+Quit the reconcile buffer.
+@end table
+
+There is also an @command{emacs} command which can be used to output
+reports in a format directly @code{read}-able from Emacs Lisp.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>201</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The Ledger tool is fast and simple, but it offers no custom method for
+actually editing the ledger. It assumes you know how to use a text
+editor, and like doing so. There is, at least, an Emacs mode that
+makes editing Ledger's data files much easier.
+
+You are also free to use GnuCash to maintain your ledger, and the
+Ledger program for querying and reporting on the contents of that
+ledger. It takes a little longer to parse the XML data format that
+GnuCash uses, but the end result is identical.
+
+Then again, why would anyone use a Gnome-centric, multi-megabyte
+behemoth to edit their data, and only a one megabyte binary to query
+it?</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>202</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The timeclock tool makes it easy to track time events, like clocking
+into and out of a particular job. These events accumulate in a
+timelog file.
+
+Each in/out event may have an optional description. If the ``in''
+description is a ledger account name, these in/out pairs may be viewed
+as virtual postings, adding time commodities (hours) to that
+account.
+
+For example, the command-line version of the timeclock tool could be
+used to begin a timelog file like:
+
+@example
+export TIMELOG=$HOME/.timelog
+ti ClientOne category
+sleep 10
+to waited for ten seconds
+@end example
+
+The @file{.timelog} file now contains:
+
+@smallexample
+i 2004/10/06 15:21:00 ClientOne category
+o 2004/10/06 15:21:10 waited for ten seconds
+@end smallexample
+
+Ledger parses this directly, as if it had seen the following transaction:
+
+@smallexample
+2004/10/06 category
+ (ClientOne) 10s
+@end smallexample
+
+In other words, the timelog event pair is seen as adding 0.00277h (ten
+seconds) worth of time to the @samp{ClientOne} account. This would be
+considered billable time, which later could be invoiced and credited
+to accounts receivable:
+
+@smallexample
+2004/11/01 (INV#1) ClientOne, Inc.
+ Receivable:ClientOne $0.10
+ ClientOne -0.00277h @@ $35.00
+@end smallexample
+
+The above posting converts the clocked time into an invoice for
+the time spent, at an hourly rate of $35. Once the invoice is paid,
+the money is deposited from the receivable account into a checking
+account:
+
+@smallexample
+2004/12/01 ClientOne, Inc.
+ Assets:Checking $0.10
+ Receivable:ClientOne
+@end smallexample
+
+And now the time spent has been turned into hard cash in the checking
+account.
+
+The advantage to using timeclock and invoicing to bill time is that
+you will always know, by looking at the balance report, epostly how
+much unbilled and unpaid time you've spent working for any particular
+client.
+
+I like to @samp{!include} my timelog at the top of my company's
+accounting ledger, with the attached prefix @samp{Billable}:
+
+@smallexample
+; -*-ledger-*-
+
+; This is the ledger file for my company. But first, include the
+; timelog data, entering all of the time events within the umbrella
+; account "Billable".
+
+!account Billable
+!include /home/johnw/.timelog
+!end
+
+; Here follows this fiscal year's postings for the company.
+
+2004/11/01 (INV#1) ClientOne, Inc.
+ Receivable:ClientOne $0.10
+ Billable:ClientOne -0.00277h @@ $35.00
+
+2004/12/01 ClientOne, Inc.
+ Assets:Checking $0.10
+ Receivable:ClientOne
+@end smallexample</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>203</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>By default, Ledger uses a human-readable data format, and displays its
+reports in a manner meant to be read on screen. For the purpose of
+writing tools which use Ledger, however, it is possible to read and
+display data using XML. This section documents that format.
+
+The general format used for Ledger data is:
+
+@smallexample
+&lt;?xml version="1.0"?&gt;
+&lt;ledger&gt;
+ &lt;xact&gt;...&lt;/xact&gt;
+ &lt;xact&gt;...&lt;/xact&gt;
+ &lt;xact&gt;...&lt;/xact&gt;...
+&lt;/ledger&gt;
+@end smallexample
+
+The data stream is enclosed in a @samp{ledger} tag, which contains a
+series of one or more transactions. Each @samp{xact} describes the transaction
+and contains a series of one or more postings:
+
+@smallexample
+&lt;xact&gt;
+ &lt;en:date&gt;2004/03/01&lt;/en:date&gt;
+ &lt;en:cleared/&gt;
+ &lt;en:code&gt;100&lt;/en:code&gt;
+ &lt;en:payee&gt;John Wiegley&lt;/en:payee&gt;
+ &lt;en:postings&gt;
+ &lt;posting&gt;...&lt;/posting&gt;
+ &lt;posting&gt;...&lt;/posting&gt;
+ &lt;posting&gt;...&lt;/posting&gt;...
+ &lt;/en:postings&gt;
+&lt;/xact&gt;
+@end smallexample
+
+The date format for @samp{en:date} is always @samp{YYYY/MM/DD}. The
+@samp{en:cleared} tag is optional, and indicates whether the
+posting has been cleared or not. There is also an
+@samp{en:pending} tag, for marking pending postings. The
+@samp{en:code} and @samp{en:payee} tags both contain whatever text the
+user wishes.
+
+After the initial transaction data, there must follow a set of postings
+marked with @samp{en:postings}. Typically these postings will
+all balance each other, but if not they will be automatically balanced
+into an account named @samp{&lt;Unknown&gt;}.
+
+Within the @samp{en:postings} tag is a series of one or more
+@samp{posting}'s, which have the following form:
+
+@smallexample
+&lt;posting&gt;
+ &lt;tr:account&gt;Expenses:Computer:Hardware&lt;/tr:account&gt;
+ &lt;tr:amount&gt;
+ &lt;value type="amount"&gt;
+ &lt;amount&gt;
+ &lt;commodity flags="PT"&gt;$&lt;/commodity&gt;
+ &lt;quantity&gt;90.00&lt;/quantity&gt;
+ &lt;/amount&gt;
+ &lt;/value&gt;
+ &lt;/tr:amount&gt;
+&lt;/posting&gt;
+@end smallexample
+
+This is a basic posting. It may also be begin with
+@samp{tr:virtual} and/or @samp{tr:generated} tags, to indicate virtual
+and auto-generated postings. Then follows the @samp{tr:account}
+tag, which contains the full name of the account the posting is
+related to. Colons separate parent from child in an account name.
+
+Lastly follows the amount of the posting, indicated by
+@samp{tr:amount}. Within this tag is a @samp{value} tag, of which
+there are four different kinds, each with its own format:
+
+@enumerate
+@item boolean
+@item integer
+@item amount
+@item balance
+@end enumerate
+
+The format of a boolean value is @samp{true} or @samp{false}
+surrounded by a @samp{boolean} tag, for example:
+
+@smallexample
+&lt;boolean&gt;true&lt;/boolean&gt;
+@end smallexample
+
+The format of an integer value is the numerical value surrounded by an
+@samp{integer} tag, for example:
+
+@smallexample
+&lt;integer&gt;12036&lt;/integer&gt;
+@end smallexample
+
+The format of an amount contains two members, the commodity and the
+quantity. The commodity can have a set of flags that indicate how to
+display it. The meaning of the flags (all of which are optional) are:
+
+@table @strong
+@item P
+The commodity is prefixed to the value.
+@item S
+The commodity is separated from the value by a space.
+@item T
+Thousands markers are used to display the amount.
+@item E
+The format of the amount is European, with period used as a thousands
+marker, and comma used as the decimal point.
+@end table
+
+The actual quantity for an amount is an integer of arbitrary size.
+Ledger uses the GNU multi-precision math library to handle such
+values. The XML format assumes the reader to be equally capable.
+Here is an example amount:
+
+@smallexample
+&lt;value type="amount"&gt;
+ &lt;amount&gt;
+ &lt;commodity flags="PT"&gt;$&lt;/commodity&gt;
+ &lt;quantity&gt;90.00&lt;/quantity&gt;
+ &lt;/amount&gt;
+&lt;/value&gt;
+@end smallexample
+
+Lastly, a balance value contains a series of amounts, each with a
+different commodity. Unlike the name, such a value does need to
+balance. It is called a balance because it sums several amounts. For
+example:
+
+@smallexample
+&lt;value type="balance"&gt;
+ &lt;balance&gt;
+ &lt;amount&gt;
+ &lt;commodity flags="PT"&gt;$&lt;/commodity&gt;
+ &lt;quantity&gt;90.00&lt;/quantity&gt;
+ &lt;/amount&gt;
+ &lt;amount&gt;
+ &lt;commodity flags="TE"&gt;DM&lt;/commodity&gt;
+ &lt;quantity&gt;200.00&lt;/quantity&gt;
+ &lt;/amount&gt;
+ &lt;/balance&gt;
+&lt;/value&gt;
+@end smallexample
+
+That is the extent of the XML data format used by Ledger. It will
+output such data if the @command{xml} command is used, and can read
+the same data.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>204</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Whenever a commodity is exchanged for another in a posting, one of the
+two is considered @emph{primary}, and the other secondary.
+Primariness of a commodity is remembered, since the @option{--market}
+option only renders balances into secondary commodities, never
+primaries. To render primaries, use the @option{--exchange=COMMODITY}
+option.
+
+In all of the following examples, the P commodity is considered primary
+and the S is secondary (the P at the beginning of the line indicates a
+price-setting directive):
+
+@smallexample
+2009/01/01 Sample 1a
+ Assets:Brokerage:Stocks 100 S
+ Assets:Brokerage:Cash -100 P
+
+P 2009/01/15 00:00:00 S 2 P
+
+2009/02/01 Sample 2a
+ Assets:Brokerage:Stocks 100 S @ 1 P
+ Assets:Brokerage:Cash
+
+P 2009/02/01 00:00:00 S 4 P
+
+2009/03/01 Sample 3a
+ Assets:Brokerage:Stocks 100 S @@ 100 P
+ Assets:Brokerage:Cash
+
+P 2009/03/01 00:00:00 S 8 P
+
+2009/04/01 Sample 4a
+ Assets:Brokerage:Cash 100 P
+ Assets:Brokerage:Stocks -100 S @{1 P@}
+
+P 2009/04/01 00:00:00 S 16 P
+@end smallexample</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>205</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Everything begins with a journal file---the anatomy of which is covered
+in detail in chapter one. To review: a @emph{journal} contains one or
+more @emph{transactions}, each of which refers to two or more
+@emph{postings}. A @emph{posting} specifies that a given
+@emph{amount} is added to, or subtracted from, an @emph{account}.
+(@emph{Accounts} may be nested hierarchically by separating the elements
+using a colon). Lastly, an @emph{amount} is a figure representing a
+given @emph{quantity} of a @emph{commodity}. Here follows a review of
+these terms, which are all used extensively throughout this chapter:
+
+@table @emph
+@item journal
+A journal is a data file containing a series of transactions.
+
+@item transaction
+a transaction relates a group of two or more postings, with the absolute
+constraint that the total sum of a transaction's postings must equal
+zero. That is, every transaction in a journal must @emph{balance} to zero.
+
+@item posting
+Postings record how commodities are moved between accounts. If you
+spent money on a movie ticket, for example, such a transaction would have two
+postings: One to show how the money was taken from your wallet, and
+another to show how it was applied to your movie expenses.
+
+@item account
+An account
+
+@item amount
+
+@item quantity
+
+@item commodity
+@end table</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>207</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Once you have a journal file representing a recent history of your
+finances, the next step is to generate reports in order to give richer
+meaning to this data. For example: Where do you spend your money? Do
+you have enough to cover upcoming expenses? Are you creating or losing
+net worth? Are your investment performing well? All of these questions
+can be answered easily with Ledger---if you know how to ask them.
+
+Preparing complex reports is not a simple task, but neither is it a
+difficult one. All that's required is a proper understanding of how
+Ledger views your data, and how it prepares it for reporting.
+
+After Ledger reads a journal file, it creates an in-memory
+representation reflecting the order and composition of those transactions.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>21</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter Example accounting practices</string>
+ <key>Title</key>
+ <string>Example accounting practices</string>
+ </dict>
+ <key>211</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The following sections discuss how Ledger is architected, from the
+ground up, and will show how to use the various parts of the Ledger
+library from your own scripts. Ledger essentially follows five steps in
+reporting data to the user:
+
+@enumerate
+@item Parse journal file into an internal representation
+@item Perform any implied math within the journal file
+@item ``Face'' this internal representation as a virtual document
+@item Apply a series of transforms to the virtual document
+@item Display the virtual document using a formatting command
+@end enumerate
+
+The calculations in step two are specified by the user, such as when a
+posting's value might contain mathematical operators. The
+calculations in step four are implied in the transformations, for
+example when the @option{--average} option is used.
+
+At the core, however, Ledger is basically a sophisticated calculator
+with special knowledge about commoditized values. It knows what you
+mean if you add ten dollars to twenty euros, and later ask for the
+balance of that particular account. So it follows that first we must
+discuss how Ledger deals with math, and from there move on to describing
+how the steps above are achieved.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>213</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The most fundamental type in Ledger is the amount, which may or may
+not have a commodity attached to it. First, we'll deal with the bare
+case, just to show how the amount type works. In C++, most all of
+Ledger's internal types end in @code{_t}; in Python, the same type
+name is used, but the @code{_t} suffix is dropped. Examples of usage
+in both languages will be presented throughout.
+
+amount_t
+commodity_t
+updater_t
+datetime_t
+balance_t
+balance_pair_t
+value_t
+valexpr_t
+format_t
+mask_t</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>214</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>journal_t
+account_t
+xact_t
+post_t
+parser_t</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>218</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@bye</string>
+ <key>Title</key>
+ <string>End Matter</string>
+ </dict>
+ <key>219</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Ledger is, at heart, just a sophisticated calculator. In addition to summing values within “accountsâ€, it guarantees that every transaction balances to zero to confirm these values are correctly transferred between accounts.
+
+In addition to using this calculator from the command-line to generate reports, you may also access it from the Python scripting language, in order to manipulate the figures however you wish. The following chapter presents the ideas you will need to know to accomplish this, as well as many typical idioms used by the Ledger module.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>22</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter Generating useful reports</string>
+ <key>Title</key>
+ <string>Generating useful reports</string>
+ </dict>
+ <key>220</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Creating a session</string>
+ <key>Title</key>
+ <string>Creating a session</string>
+ </dict>
+ <key>221</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>All interactions with the Ledger library take place in the context of a @var{Session}. You may create as many sessions as you like, though typically only one is needed during the lifetime of a scriptAn example where more might be needed is a GUI program that opens multiple Ledger files in different windows, and creates reports for each file separately. Ledger provides a pre-initialized session named @var{session}, but others can still be created. Creating a session is trivial, but before it may be used it must be passed in a call to @code{set_session_context}. This is how multiple sessions are managed in a multi-threaded environment, where the session itself should be considered non-reentrant.
+
+The first operation after creating a session is typically to load the Ledger data you wish to report on for that session. The loaded data can be reset at any time, and can also be modified.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>222</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string>Example of creating a session, reading some journal data, and generating a simplistic report.</string>
+ <key>Text</key>
+ <string>from ledger import *
+
+session.read_journal("doc/sample.dat")
+
+new_session = Session()
+
+set_session_context(new_session)
+session.read_journal("doc/sample.dat")
+set_session_content(session) # restore the default session
+
+for txn in session.journal.transactions:
+ print txn.payee
+
+ for p in txn.postings:
+ print p.account, "-&gt;", p.amount</string>
+ <key>Title</key>
+ <string>Initialize a session</string>
+ </dict>
+ <key>224</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string>Notes folder</string>
+ <key>Text</key>
+ <string></string>
+ <key>Title</key>
+ <string>Notes</string>
+ </dict>
+ <key>225</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string>Note on: Content</string>
+ <key>Text</key>
+ <string></string>
+ <key>Title</key>
+ <string>Note (Content), 22 Jun 2009, 17:51</string>
+ </dict>
+ <key>23</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter Value expressions</string>
+ <key>Title</key>
+ <string>Value expressions</string>
+ </dict>
+ <key>24</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter Format strings</string>
+ <key>Title</key>
+ <string>Format strings</string>
+ </dict>
+ <key>25</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter Scripting in Python</string>
+ <key>Title</key>
+ <string>Scripting in Python</string>
+ </dict>
+ <key>26</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter The design of Ledger</string>
+ <key>Title</key>
+ <string>The design of Ledger</string>
+ </dict>
+ <key>28</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Commands</string>
+ <key>Title</key>
+ <string>Commands</string>
+ </dict>
+ <key>29</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Options</string>
+ <key>Title</key>
+ <string>Options</string>
+ </dict>
+ <key>30</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Period expressions</string>
+ <key>Title</key>
+ <string>Period expressions</string>
+ </dict>
+ <key>31</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Format strings</string>
+ <key>Title</key>
+ <string>Format strings</string>
+ </dict>
+ <key>32</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Value expressions</string>
+ <key>Title</key>
+ <string>Value expressions</string>
+ </dict>
+ <key>33</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section File format</string>
+ <key>Title</key>
+ <string>File format</string>
+ </dict>
+ <key>4</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>\input texinfo @c -*-texinfo-*-
+
+@setfilename ledger.info
+@settitle Ledger: Command-Line Accounting
+
+@dircategory User Applications</string>
+ <key>Title</key>
+ <string>Front Matter</string>
+ </dict>
+ <key>44</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection balance</string>
+ <key>Title</key>
+ <string>balance</string>
+ </dict>
+ <key>5</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@copying
+Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ 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.
+@end copying
+
+@documentencoding utf-8
+
+@iftex
+@finalout
+@end iftex
+
+@titlepage
+@title Ledger: Command-Line Accounting
+@author John Wiegley
+@end titlepage
+
+@direntry
+* Ledger: (ledger). Command Line Accounting
+@end direntry
+
+@contents
+
+@ifnottex
+@top Overview
+
+@insertcopying
+@end ifnottex
+
+@ifnottex
+@section Copyright
+@insertcopying
+@end ifnottex</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>54</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection register</string>
+ <key>Title</key>
+ <string>register</string>
+ </dict>
+ <key>55</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection print</string>
+ <key>Title</key>
+ <string>print</string>
+ </dict>
+ <key>56</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection output</string>
+ <key>Title</key>
+ <string>output</string>
+ </dict>
+ <key>57</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection xml</string>
+ <key>Title</key>
+ <string>xml</string>
+ </dict>
+ <key>58</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection emacs</string>
+ <key>Title</key>
+ <string>emacs</string>
+ </dict>
+ <key>59</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection equity</string>
+ <key>Title</key>
+ <string>equity</string>
+ </dict>
+ <key>6</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@chapter Introduction</string>
+ <key>Title</key>
+ <string>Introduction</string>
+ </dict>
+ <key>60</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection prices</string>
+ <key>Title</key>
+ <string>prices</string>
+ </dict>
+ <key>61</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection xact</string>
+ <key>Title</key>
+ <string>xact</string>
+ </dict>
+ <key>62</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Basic options</string>
+ <key>Title</key>
+ <string>Basic options</string>
+ </dict>
+ <key>63</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Report filtering</string>
+ <key>Title</key>
+ <string>Report filtering</string>
+ </dict>
+ <key>64</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Output customization</string>
+ <key>Title</key>
+ <string>Output customization</string>
+ </dict>
+ <key>65</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Commodity reporting</string>
+ <key>Title</key>
+ <string>Commodity reporting</string>
+ </dict>
+ <key>66</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Environment variables</string>
+ <key>Title</key>
+ <string>Environment variables</string>
+ </dict>
+ <key>67</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Variables</string>
+ <key>Title</key>
+ <string>Variables</string>
+ </dict>
+ <key>69</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Functions</string>
+ <key>Title</key>
+ <string>Functions</string>
+ </dict>
+ <key>7</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>Ledger is an accounting tool with the moxie to exist. It provides no
+bells or whistles, and returns the user to the days before user
+interfaces were even a twinkling in their father's CRT.
+
+What it does offer is a double-entry accounting ledger with all the
+flexibility and muscle of its modern day cousins, without any of the
+fat. Think of it as the Bran Muffin of accounting tools.
+
+To use it, you need to start keeping a ledger. This is the basis of
+all accounting, and if you haven't started yet, now is the time to
+learn. The little booklet that comes with your checkbook is a ledger,
+so we'll describe double-entry accounting in terms of that.
+
+A checkbook ledger records debits (subtractions, or withdrawals) and
+credits (additions, or deposits) with reference to a single account:
+the checking account. Where the money comes from, and where it goes
+to, are described in the payee field, where you write the person or
+company's name. The ultimate aim of keeping a checkbook ledger is to
+know how much money is available to spend. That's really the aim of
+all ledgers.
+
+What computers add is the ability to walk through these postings,
+and tell you things about your spending habits; to let you devise
+budgets and get control over your spending; to squirrel away money
+into virtual savings account without having to physically move money
+around; etc. As you keep your ledger, you are recording information
+about your life and habits, and sometimes that information can start
+telling you things you aren't aware of. Such is the aim of all good
+accounting tools.
+
+The next step up from a checkbook ledger, is a ledger that keeps track
+of all your accounts, not just checking. In such a ledger, you record
+not only who gets paid---in the case of a debit---but where the money
+came from. In a checkbook ledger, its assumed that all the money
+comes from your checking account. But in a general ledger, you write
+posting two-lines: the source account and target account.
+@emph{There must always be a debit from at least one account for every
+credit made to another account}. This is what is meant by
+``double-entry'' accounting: the ledger must always balance to zero,
+with an equal number of debits and credits.
+
+For example, let's say you have a checking account and a brokerage
+account, and you can write checks from both of them. Rather than keep
+two checkbooks, you decide to use one ledger for both. In this
+general ledger you need to record a payment to Pacific Bell for your
+monthly phone bill. The cost is $23.00, let's say, and you want to
+pay it from your checking account. In the general ledger you need to
+say where the money came from, in addition to where it's going to.
+The transaction might look like this:
+
+@smallexample
+9/29 BAL Pacific Bell $-200.00 $-200.00
+ Equity:Opening Balances $200.00
+9/29 BAL Checking $100.00 $100.00
+ Equity:Opening Balances $-100.00
+9/29 100 Pacific Bell $23.00 $223.00
+ Checking $-23.00 $77.00
+@end smallexample
+
+The first line shows a payment to Pacific Bell for $23.00. Because
+there is no ``balance'' in a general ledger---it's always zero---we
+write in the total balance of all payments to ``Pacific Bell'', which
+now is $223.00 (previously the balance was $200.00). This is done by
+looking at the last transaction for ``Pacific Bell'' in the ledger, adding
+$23.00 to that amount, and writing the total in the balance column.
+And the money came from ``Checking''---a withdrawal of $23.00---which
+leaves the ending balance in ``Checking'' at $77.00. This is a very
+manual procedure; but that's where computers come in...
+
+The posting must balance to $0: $23 went to Pacific Bell, $23 came
+from Checking. There is nothing left over to be accounted for, since
+the money has simply moved from one account to another. This is the
+basis of double-entry accounting: that money never pops in or out of
+existence; it is always a posting from one account to another.
+
+Keeping a general ledger is the same as keeping two separate ledgers:
+One for Pacific Bell and one for Checking. In that case, each time a
+payment is written into one, you write a corresponding withdrawal into
+the other. This makes it easier to write in a ``running balance'',
+since you don't have to look back at the last time the account was
+referenced---but it also means having a lot of ledger books, if you
+deal with multiple accounts.
+
+Enter the beauty of computerized accounting. The purpose of the
+Ledger program is to make general ledger accounting simple, by keeping
+track of the balances for you. Your only job is to enter the
+postings. If a posting does not balance, Ledger displays an
+error and indicates the incorrect posting.@footnote{In some
+special cases, it automatically balances this transaction for you.}
+
+In summary, there are two aspects of Ledger use: updating the ledger
+data file, and using the Ledger tool to view the summarized result of
+your transactions.
+
+And just for the sake of example---as a starting point for those who
+want to dive in head-first---here are the ledger transactions from above,
+formatting as the ledger program wishes to see them:
+
+@smallexample
+2004/09/29 Pacific Bell
+ Payable:Pacific Bell $-200.00
+ Equity:Opening Balances
+
+2004/09/29 Checking
+ Accounts:Checking $100.00
+ Equity:Opening Balances
+
+2004/09/29 Pacific Bell
+ Payable:Pacific Bell $23.00
+ Accounts:Checking
+@end smallexample
+
+The account balances and registers in this file, if saved as
+@file{ledger.dat}, could be reported using:
+
+@example
+$ ledger -f ledger.dat balance
+$ ledger -f ledger.dat register checking
+$ ledger -f ledger.dat register bell
+@end example</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>70</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Operators</string>
+ <key>Title</key>
+ <string>Operators</string>
+ </dict>
+ <key>71</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Complex expressions</string>
+ <key>Title</key>
+ <string>Complex expressions</string>
+ </dict>
+ <key>72</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsubsection Posting/account details</string>
+ <key>Title</key>
+ <string>Posting/account details</string>
+ </dict>
+ <key>73</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsubsection Calculated totals</string>
+ <key>Title</key>
+ <string>Calculated totals</string>
+ </dict>
+ <key>74</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Checking balances</string>
+ <key>Title</key>
+ <string>Checking balances</string>
+ </dict>
+ <key>75</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section The register report</string>
+ <key>Title</key>
+ <string>The register report</string>
+ </dict>
+ <key>76</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Selecting postings</string>
+ <key>Title</key>
+ <string>Selecting postings</string>
+ </dict>
+ <key>77</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Massaging register output</string>
+ <key>Title</key>
+ <string>Massaging register output</string>
+ </dict>
+ <key>78</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Standard queries</string>
+ <key>Title</key>
+ <string>Standard queries</string>
+ </dict>
+ <key>79</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Reporting balance totals</string>
+ <key>Title</key>
+ <string>Reporting balance totals</string>
+ </dict>
+ <key>8</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section More introduction</string>
+ <key>Title</key>
+ <string>More introduction</string>
+ </dict>
+ <key>80</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Reporting percentages</string>
+ <key>Title</key>
+ <string>Reporting percentages</string>
+ </dict>
+ <key>81</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Sub-account balances</string>
+ <key>Title</key>
+ <string>Sub-account balances</string>
+ </dict>
+ <key>82</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Specific account balances</string>
+ <key>Title</key>
+ <string>Specific account balances</string>
+ </dict>
+ <key>83</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Specific register queries</string>
+ <key>Title</key>
+ <string>Specific register queries</string>
+ </dict>
+ <key>84</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection By date</string>
+ <key>Title</key>
+ <string>By date</string>
+ </dict>
+ <key>85</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection By status</string>
+ <key>Title</key>
+ <string>By status</string>
+ </dict>
+ <key>86</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection By relationship</string>
+ <key>Title</key>
+ <string>By relationship</string>
+ </dict>
+ <key>87</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection By budget</string>
+ <key>Title</key>
+ <string>By budget</string>
+ </dict>
+ <key>88</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection By value expression</string>
+ <key>Title</key>
+ <string>By value expression</string>
+ </dict>
+ <key>89</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Summarizing</string>
+ <key>Title</key>
+ <string>Summarizing</string>
+ </dict>
+ <key>9</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>The most important part of accounting is keeping a good ledger. If
+you have a good ledger, tools can be written to work whatever
+mathematically tricks you need to better understand your spending
+patterns. Without a good ledger, no tool, however smart, can help
+you.
+
+The Ledger program aims at making ledger transaction as simple as possible.
+Since it is a command-line tool, it does not provide a user interface
+for keeping a ledger. If you like, you may use GnuCash to maintain
+your ledger, in which case the Ledger program will read GnuCash's data
+files directly. In that case, read the GnuCash manual now, and skip
+to the next chapter.
+
+If you are not using GnuCash, but a text editor to maintain your
+ledger, read on. Ledger has been designed to make data transaction as
+simple as possible, by keeping the ledger format easy, and also by
+automagically determining as much information as possible based on the
+nature of your transactions.
+
+For example, you do not need to tell Ledger about the accounts you
+use. Any time Ledger sees a posting involving an account it knows
+nothing about, it will create it. If you use a commodity that is new
+to Ledger, it will create that commodity, and determine its display
+characteristics (placement of the symbol before or after the amount,
+display precision, etc) based on how you used the commodity in the
+posting.
+
+Here is the Pacific Bell example from above, given as a Ledger
+posting:
+
+@smallexample
+9/29 (100) Pacific Bell
+ Expenses:Utilities:Phone $23.00
+ Assets:Checking $-23.00
+@end smallexample
+
+As you can see, it is very similar to what would be written on paper,
+minus the computed balance totals, and adding in account names that
+work better with Ledger's scheme of things. In fact, since Ledger is
+smart about many things, you don't need to specify the balanced
+amount, if it is the same as the first line:
+
+@smallexample
+9/29 (100) Pacific Bell
+ Expenses:Utilities:Phone $23.00
+ Assets:Checking
+@end smallexample
+
+For this transaction, Ledger will figure out that $-23.00 must come from
+@samp{Assets:Checking} in order to balance the transaction.</string>
+ <key>Title</key>
+ <string>Content</string>
+ </dict>
+ <key>90</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Quick periods</string>
+ <key>Title</key>
+ <string>Quick periods</string>
+ </dict>
+ <key>91</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Ordering and width</string>
+ <key>Title</key>
+ <string>Ordering and width</string>
+ </dict>
+ <key>92</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Averages and percentages</string>
+ <key>Title</key>
+ <string>Averages and percentages</string>
+ </dict>
+ <key>93</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Reporting total data</string>
+ <key>Title</key>
+ <string>Reporting total data</string>
+ </dict>
+ <key>94</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Display by value expression</string>
+ <key>Title</key>
+ <string>Display by value expression</string>
+ </dict>
+ <key>95</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Change report format</string>
+ <key>Title</key>
+ <string>Change report format</string>
+ </dict>
+ <key>96</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Stating where money goes</string>
+ <key>Title</key>
+ <string>Stating where money goes</string>
+ </dict>
+ <key>97</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Assets and Liabilities</string>
+ <key>Title</key>
+ <string>Assets and Liabilities</string>
+ </dict>
+ <key>98</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@subsection Tracking reimbursable expenses</string>
+ <key>Title</key>
+ <string>Tracking reimbursable expenses</string>
+ </dict>
+ <key>99</key>
+ <dict>
+ <key>Notes</key>
+ <string></string>
+ <key>Synopsis</key>
+ <string></string>
+ <key>Text</key>
+ <string>@section Typical queries</string>
+ <key>Title</key>
+ <string>Typical queries</string>
+ </dict>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/ExportSettings.xml b/doc/Ledger.scriv/ExportSettings.xml
new file mode 100644
index 00000000..46e31a4d
--- /dev/null
+++ b/doc/Ledger.scriv/ExportSettings.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>SCRExportAnnotationsAsRTFCommentsKey</key>
+ <false/>
+ <key>SCRExportConvertEllipsesToTriplePeriodsKey</key>
+ <true/>
+ <key>SCRExportConvertEmDashesToDoubleHyphensKey</key>
+ <true/>
+ <key>SCRExportConvertItalicsToUnderlineKey</key>
+ <true/>
+ <key>SCRExportCountFirstPageKey</key>
+ <false/>
+ <key>SCRExportDisableAutoNumberingKey</key>
+ <false/>
+ <key>SCRExportDoNotIndentTitlesKey</key>
+ <false/>
+ <key>SCRExportDocumentsToExportTagKey</key>
+ <integer>0</integer>
+ <key>SCRExportEndOfTextMarkerKey</key>
+ <string>&lt;&lt;&lt;&lt;&gt;&gt;&gt;&gt;</string>
+ <key>SCRExportFootnotesTypeKey</key>
+ <integer>0</integer>
+ <key>SCRExportFormatTypeKey</key>
+ <integer>2</integer>
+ <key>SCRExportGroupIDKey</key>
+ <integer>0</integer>
+ <key>SCRExportGroupTitleFontKey</key>
+ <data>
+ BAtzdHJlYW10eXBlZIHoA4QBQISEhAZOU0ZvbnQehIQITlNPYmplY3QAhYQBaRiEBVsy
+ NGNdBgAAABAAAAD//kMAbwB1AHIAaQBlAHIAhAFmDIQBYwCYAZgAmACG
+ </data>
+ <key>SCRExportGroupTitleIsCenteredKey</key>
+ <true/>
+ <key>SCRExportHeaderFooterAlignmentKey</key>
+ <integer>1</integer>
+ <key>SCRExportHeaderFooterTypeKey</key>
+ <integer>0</integer>
+ <key>SCRExportIncludeFootnotesKey</key>
+ <true/>
+ <key>SCRExportMarkEndOfTextKey</key>
+ <false/>
+ <key>SCRExportNoHeaderFooterOnFirstPageKey</key>
+ <true/>
+ <key>SCRExportRemoveAnnotationsKey</key>
+ <true/>
+ <key>SCRExportSceneBreakStringKey</key>
+ <string>#</string>
+ <key>SCRExportSectionSeparatorKey</key>
+ <integer>0</integer>
+ <key>SCRExportStraightenTypographersQuotesKey</key>
+ <true/>
+ <key>SCRExportTextAttributesAppliesToFontOnlyKey</key>
+ <false/>
+ <key>SCRExportTextAttributesKey</key>
+ <data>
+ BAtzdHJlYW10eXBlZIHoA4QBQISEhAxOU0RpY3Rpb25hcnkAhIQITlNPYmplY3QAhYQB
+ aQKShISECE5TU3RyaW5nAZSEASsQTlNQYXJhZ3JhcGhTdHlsZYaShISEF05TTXV0YWJs
+ ZVBhcmFncmFwaFN0eWxlAISEEE5TUGFyYWdyYXBoU3R5bGUAlIQEQ0NAUwQAhYGQAIQE
+ WzJmXRwChpKElpcGTlNGb250hpKEhIQGTlNGb250HpSVGIQFWzI0Y10GAAAAEAAAAP/+
+ QwBvAHUAcgBpAGUAcgCEAWYMhAFjAJ8BnwCfAIaG
+ </data>
+ <key>SCRExportTextContainerTitleFontKey</key>
+ <data>
+ BAtzdHJlYW10eXBlZIHoA4QBQISEhAZOU0ZvbnQehIQITlNPYmplY3QAhYQBaRiEBVsy
+ NGNdBgAAABAAAAD//kMAbwB1AHIAaQBlAHIAhAFmDIQBYwCYAZgAmACG
+ </data>
+ <key>SCRExportTextContainerTitleIsCenteredKey</key>
+ <true/>
+ <key>SCRExportTextTitleFontKey</key>
+ <data>
+ BAtzdHJlYW10eXBlZIHoA4QBQISEhAZOU0ZvbnQehIQITlNPYmplY3QAhYQBaRiEBVsy
+ NGNdBgAAABAAAAD//kMAbwB1AHIAaQBlAHIAhAFmDIQBYwCYAZgAmACG
+ </data>
+ <key>SCRExportTextTitleIsCenteredKey</key>
+ <true/>
+ <key>SCRExportUseExportTextAttributesKey</key>
+ <true/>
+ <key>SCRIncludeGroupDocumentTextKey</key>
+ <true/>
+ <key>SCRIncludeGroupMetaDataKey</key>
+ <false/>
+ <key>SCRIncludeGroupNotesKey</key>
+ <false/>
+ <key>SCRIncludeGroupSynopsesKey</key>
+ <false/>
+ <key>SCRIncludeGroupTitlesKey</key>
+ <false/>
+ <key>SCRIncludeTextDocumentTextKey</key>
+ <true/>
+ <key>SCRIncludeTextGroupDocumentTextKey</key>
+ <true/>
+ <key>SCRIncludeTextGroupMetaDataKey</key>
+ <false/>
+ <key>SCRIncludeTextGroupNotesKey</key>
+ <false/>
+ <key>SCRIncludeTextGroupSynopsesKey</key>
+ <false/>
+ <key>SCRIncludeTextGroupTitlesKey</key>
+ <false/>
+ <key>SCRIncludeTextMetaDataKey</key>
+ <true/>
+ <key>SCRIncludeTextNotesKey</key>
+ <false/>
+ <key>SCRIncludeTextSynopsesKey</key>
+ <false/>
+ <key>SCRIncludeTextTitlesKey</key>
+ <false/>
+ <key>SCRSavedExportSettings</key>
+ <dict/>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/ProjectNotes.rtfd/TXT.rtf b/doc/Ledger.scriv/ProjectNotes.rtfd/TXT.rtf
new file mode 100644
index 00000000..60480d02
--- /dev/null
+++ b/doc/Ledger.scriv/ProjectNotes.rtfd/TXT.rtf
@@ -0,0 +1,4 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1038
+{\fonttbl}
+{\colortbl;\red255\green255\blue255;}
+} \ No newline at end of file
diff --git a/doc/Ledger.scriv/QuickLook/Preview.html b/doc/Ledger.scriv/QuickLook/Preview.html
new file mode 100644
index 00000000..81db790e
--- /dev/null
+++ b/doc/Ledger.scriv/QuickLook/Preview.html
@@ -0,0 +1,563 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<title></title>
+<meta name="Generator" content="Cocoa HTML Writer">
+<meta name="CocoaVersion" content="1038">
+<style type="text/css">
+p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; background-color: #dee4ea}
+p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Courier}
+p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Courier; min-height: 14.0px}
+</style>
+</head>
+<body>
+<p class="p1"><b>• Front Matter</b></p>
+<p class="p2">\input texinfo<span class="Apple-converted-space">  </span>@c -*-texinfo-*-<span class="Apple-converted-space">  </span>@setfilename ledger.info @settitle Ledger: Command-Line Accounting<span class="Apple-converted-space">  </span>@dircategory User Applications</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@copying Copyright (c) 2003-2009, John Wiegley.<span class="Apple-converted-space">  </span>All rights reserved.<span class="Apple-converted-space">  </span>Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:<span class="Apple-converted-space">  </span>- Redistributions of source code must retain the above copyright <span class="Apple-converted-space">  </span>notice, this list of conditions and the following disclaimer.<span class="Apple-converted-space">  </span>- Redistributions in binary form must reproduce the above copyright <span class="Apple-converted-space">  </span>notice, this list of conditions and the following disclaimer in the <span class="Apple-converted-space">  </span>documentation a...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Introduction</b></p>
+<p class="p2">@chapter Introduction</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Ledger is an accounting tool with the moxie to exist.<span class="Apple-converted-space">  </span>It provides no bells or whistles, and returns the user to the days before user interfaces were even a twinkling in their father's CRT.<span class="Apple-converted-space">  </span>What it does offer is a double-entry accounting ledger with all the flexibility and muscle of its modern day cousins, without any of the fat.<span class="Apple-converted-space">  </span>Think of it as the Bran Muffin of accounting tools.<span class="Apple-converted-space">  </span>To use it, you need to start keeping a ledger.<span class="Apple-converted-space">  </span>This is the basis of all accounting, and if you haven't started y...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• More introduction</b></p>
+<p class="p2">@section More introduction</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The most important part of accounting is keeping a good ledger.<span class="Apple-converted-space">  </span>If you have a good ledger, tools can be written to work whatever mathematically tricks you need to better understand your spending patterns.<span class="Apple-converted-space">  </span>Without a good ledger, no tool, however smart, can help you.<span class="Apple-converted-space">  </span>The Ledger program aims at making ledger transaction as simple as possible. Since it is a command-line tool, it does not provide a user interface for keeping a ledger.<span class="Apple-converted-space">  </span>If you like, you may use GnuCash to maintain your ledger, in w...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Building the program</b></p>
+<p class="p2">@section Building the program</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Ledger is written in ANSI C++, and should compile on any platform.<span class="Apple-converted-space">  </span>It depends on the GNU multiprecision integer library (libgmp), and the Perl regular expression library (libpcre).<span class="Apple-converted-space">  </span>It was developed using GNU make and gcc 3.3, on a PowerBook running OS/X.<span class="Apple-converted-space">  </span>To build and install once you have these libraries on your system, enter these commands:<span class="Apple-converted-space">  </span>@example ./configure &amp;&amp; make install @end example</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Getting help</b></p>
+<p class="p2">@section Getting help</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">If you need help on how to use Ledger, or run into problems, you can just the Ledger mailing list at the following Web address:<span class="Apple-converted-space">  </span>@example https://lists.sourceforge.net/lists/listinfo/ledger-discuss @end example<span class="Apple-converted-space">  </span>You can also find help at the @samp{#ledger} channel on the IRC server @samp{irc.freenode.net}.</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Quick Reference</b></p>
+<p class="p2">@chapter Quick Reference</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">This chapter describes ledger's features and serves as a quick reference. You may wish to survey this to get an overview before diving in to the @ref{Ledger Tutorial} and more detailed examples that follow.<span class="Apple-converted-space">  </span>Ledger has a very simple command-line interface, named---enticing enough---@command{ledger}.<span class="Apple-converted-space">  </span>It supports a few reporting commands, and a large number of options for refining the output from those commands. The basic syntax of any ledger command is:<span class="Apple-converted-space">  </span>@example ledger [OPTIONS...] COMMAND [ARG...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Commands</b></p>
+<p class="p2">@section Commands</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• balance</b></p>
+<p class="p2">@subsection balance</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The @command{balance} command reports the current balance of all accounts.<span class="Apple-converted-space">  </span>It accepts a list of optional regexps, which confine the balance report to the matching accounts.<span class="Apple-converted-space">  </span>If an account contains multiple types of commodities, each commodity's total is reported separately.<span class="Apple-converted-space"> </span></p>
+<p class="p3"><br></p>
+<p class="p1"><b>• register</b></p>
+<p class="p2">@subsection register</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The @command{register} command displays all the postings occurring in a single account, line by line.<span class="Apple-converted-space">  </span>The account regexp must be specified as the only argument to this command.<span class="Apple-converted-space">  </span>If any regexps occur after the required account name, the register will contain only those postings that match.<span class="Apple-converted-space">  </span>Very useful for hunting down a particular posting.<span class="Apple-converted-space">  </span>The output from @command{register} is very close to what a typical checkbook, or single-account ledger, would look like.<span class="Apple-converted-space">  </span>It also shows a running balance.<span class="Apple-converted-space">  </span>...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• print</b></p>
+<p class="p2">@subsection print</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The @command{print} command prints out ledger transactions in a textual format that can be parsed by Ledger.<span class="Apple-converted-space">  </span>They will be properly formatted, and output in the most economic form possible.<span class="Apple-converted-space">  </span>The ``print'' command also takes a list of optional regexps, which will cause only those postings which match in some way to be printed.<span class="Apple-converted-space">  </span>The @command{print} command can be a handy way to clean up a ledger file whose formatting has gotten out of hand.</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• output</b></p>
+<p class="p2">@subsection output</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The @command{output} command is very similar to the @command{print} command, except that it attempts to replicate the specified ledger file epostly.<span class="Apple-converted-space">  </span>The format of the command is:<span class="Apple-converted-space">  </span>@example ledger -f FILENAME output FILENAME @end example<span class="Apple-converted-space">  </span>Where @file{FILENAME} is the name of the ledger file to output.<span class="Apple-converted-space">  </span>The reason for specifying this command is that only transactions contained within that file will be output, and not an included transactions (as can happen with the @command{print} command).</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• xml</b></p>
+<p class="p2">@subsection xml</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The @command{xml} command outputs results similar to what @command{print} and @command{register} display, but as an XML form. This data can then be read in and processed.<span class="Apple-converted-space">  </span>Use the @option{--totals} option to include the running total with each posting.</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• emacs</b></p>
+<p class="p2">@subsection emacs</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The @command{emacs} command outputs results in a form that can be read directly by Emacs Lisp.<span class="Apple-converted-space">  </span>The format of the sexp is:<span class="Apple-converted-space">  </span>@example ((BEG-POS CLEARED DATE CODE PAYEE <span class="Apple-converted-space">  </span>(ACCOUNT AMOUNT)...)<span class="Apple-converted-space">  </span>; list of postings<span class="Apple-converted-space">  </span>...) <span class="Apple-converted-space">                  </span>; list of transactions @end example</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• equity</b></p>
+<p class="p2">@subsection equity</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The @command{equity} command prints out accounts balances as if they were transactions.<span class="Apple-converted-space">  </span>This makes it easy to establish the starting balances for an account, such as when @ref{Archiving previous years}.</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• prices</b></p>
+<p class="p2">@subsection prices</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The @command{prices} command displays the price history for matching commodities.<span class="Apple-converted-space">  </span>The @option{-A} flag is useful with this report, to display the running average price, or @option{-D} to show each price's deviation from that average.<span class="Apple-converted-space">  </span>There is also a @command{pricesdb} command which outputs the same information as @command{prices}, but does in a format that can be parsed by Ledger.</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• xact</b></p>
+<p class="p2">@subsection xact</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The @command{xact} commands simplifies the creation of new transactions. It works on the principle that 80% of all postings are variants of earlier postings.<span class="Apple-converted-space">  </span>Here's how it works:<span class="Apple-converted-space">  </span>Say you currently have this posting in your ledger file:<span class="Apple-converted-space">  </span>@smallexample 2004/03/15 * Viva Italiano <span class="Apple-converted-space">    </span>Expenses:Food <span class="Apple-converted-space">                      </span>$12.45 <span class="Apple-converted-space">    </span>Expenses:Tips<span class="Apple-converted-space">                        </span>$2.55 <span class="Apple-converted-space">    </span>Liabilities:MasterCard <span class="Apple-converted-space">            </span>$-15.00 @end smallexample<span class="Apple-converted-space">  </span>Now it's @samp{2004/4/9}, and you've just eating at @samp{Vi...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Options</b></p>
+<p class="p2">@section Options</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">With all of the reports, command-line options are useful to modify the output generated.<span class="Apple-converted-space">  </span>These command-line options always occur before the command word.<span class="Apple-converted-space">  </span>This is done to distinguish options from exclusive regular expressions, which also begin with a dash.<span class="Apple-converted-space">  </span>The basic form for most commands is:<span class="Apple-converted-space">  </span>@example ledger [OPTIONS] COMMAND [REGEXPS...] [-- [REGEXPS...]] @end example<span class="Apple-converted-space">  </span>The @var{OPTIONS} and @var{REGEXPS} expressions are both optional. You could just use @samp{ledger balance}, without any opt...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Basic options</b></p>
+<p class="p2">@subsection Basic options</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">These are the most basic command options.<span class="Apple-converted-space">  </span>Most likely, the user will want to set them using environment variables (see @ref{Options}), instead of using actual command-line options:<span class="Apple-converted-space">  </span>@option{--help} (@option{-h}) prints a summary of all the options, and what they are used for.<span class="Apple-converted-space">  </span>This can be a handy way to remember which options do what.<span class="Apple-converted-space">  </span>This help screen is also printed if ledger is run without a command.<span class="Apple-converted-space">  </span>@option{--version} (@option{-v}) prints the current version of ledger and exits.<span class="Apple-converted-space">  </span>This is u...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Report filtering</b></p>
+<p class="p2">@subsection Report filtering</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">These options change which postings affect the outcome of a report, in ways other than just using regular expressions:<span class="Apple-converted-space">  </span>@option{--current}(@option{-c}) displays only transactions occurring on or before the current date.<span class="Apple-converted-space">  </span>@option{--begin DATE} (@option{-b DATE}) constrains the report to transactions on or after @var{DATE}.<span class="Apple-converted-space">  </span>Only transactions after that date will be calculated, which means that the running total in the balance report will always start at zero with the first matching transaction.<span class="Apple-converted-space">  </span>...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Output customization</b></p>
+<p class="p2">@subsection Output customization</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">These options affect only the output, but not which postings are used to create it:<span class="Apple-converted-space">  </span>@option{--collapse} (@option{-n}) causes transactions in a @command{register} report with multiple postings to be collapsed into a single, subtotaled transaction.<span class="Apple-converted-space">  </span>@option{--subtotal} (@option{-s}) causes all transactions in a @command{register} report to be collapsed into a single, subtotaled transaction.<span class="Apple-converted-space">  </span>@option{--by-payee} (@option{-P}) reports subtotals by payee.<span class="Apple-converted-space">  </span>@option{--comm-as-payee} (@option{-x}) chan...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Commodity reporting</b></p>
+<p class="p2">@subsection Commodity reporting</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">These options affect how commodity values are displayed:<span class="Apple-converted-space">  </span>@option{--price-db FILE} sets the file that is used for recording downloaded commodity prices.<span class="Apple-converted-space">  </span>It is always read on startup, to determine historical prices.<span class="Apple-converted-space">  </span>Other settings can be placed in this file manually, to prevent downloading quotes for a specific, for example.<span class="Apple-converted-space">  </span>This is done by adding a line like the following:<span class="Apple-converted-space">  </span>@example ; Don't download quotes for the dollar, or timelog values N $ N h @end example<span class="Apple-converted-space">  </span>@option{--price-exp MINS} (@opt...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Environment variables</b></p>
+<p class="p2">@subsection Environment variables</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Every option to ledger may be set using an environment variable.<span class="Apple-converted-space">  </span>If an option has a long name such @option{--this-option}, setting the environment variable @env{LEDGER_THIS_OPTION} will have the same affect as specifying that option on the command-line.<span class="Apple-converted-space">  </span>Options on the command-line always take precedence over environment variable settings, however.<span class="Apple-converted-space">  </span>Note that you may also permanently specify option values by placing option settings in the file @file{~/.ledgerrc}, for example:<span class="Apple-converted-space">  </span>@example --cache ...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Period expressions</b></p>
+<p class="p2">@section Period expressions</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">A period expression indicates a span of time, or a reporting interval, or both.<span class="Apple-converted-space">  </span>The full syntax is:<span class="Apple-converted-space">  </span>@example [INTERVAL] [BEGIN] [END] @end example<span class="Apple-converted-space">  </span>The optional @var{INTERVAL} part may be any one of:<span class="Apple-converted-space">  </span>@example every day every week every monthly every quarter every year every N days <span class="Apple-converted-space">    </span># N is any integer every N weeks every N months every N quarters every N years daily weekly biweekly monthly bimonthly quarterly yearly @end example<span class="Apple-converted-space">  </span>After the interval, a begin time, end time, both or neither m...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Format strings</b></p>
+<p class="p2">@section Format strings</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Format strings may be used to change the output format of reports. They are specified by passing a formatting string to the @option{--format} (@option{-F}) option.<span class="Apple-converted-space">  </span>Within that string, constructs are allowed which make it possible to display the various parts of an account or posting in custom ways.<span class="Apple-converted-space">  </span>Within a format strings, a substitution is specified using a percent character (@samp{%}).<span class="Apple-converted-space">  </span>The basic format of all substitutions is:<span class="Apple-converted-space">  </span>@example %[-][MIN WIDTH][.MAX WIDTH]EXPR @end example<span class="Apple-converted-space">  </span>If the o...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Value expressions</b></p>
+<p class="p2">@section Value expressions</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Value expressions are an expression language used by Ledger to calculate values used by the program for many different purposes:<span class="Apple-converted-space">  </span>@enumerate @item The values displayed in reports @item For predicates (where truth is anything non-zero), to determine which postings are calculated (@option{-l}) or displayed (@option{-d}). @item For sorting criteria, to yield the sort key. @item In the matching criteria used by automated postings. @end enumerate<span class="Apple-converted-space">  </span>Value expressions support most simple math and logic ...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Variables</b></p>
+<p class="p2">@subsection Variables</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Below are the one letter variables available in any value expression. For the register and print commands, these variables relate to individual postings, and sometimes the account affected by a posting.<span class="Apple-converted-space">  </span>For the balance command, these variables relate to accounts---often with a subtle difference in meaning.<span class="Apple-converted-space">  </span>The use of each variable for both is specified.<span class="Apple-converted-space">  </span>@table @code @item t This maps to whatever the user specified with @option{-t}.<span class="Apple-converted-space">  </span>In a register report, @option{-t} changes the value column; ...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Posting/account details</b></p>
+<p class="p2">@subsubsection Posting/account details</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@table @code @item d A posting's date, as the number of seconds past the epoch.<span class="Apple-converted-space">  </span>This is always ``today'' for an account.<span class="Apple-converted-space">  </span>@item a The posting's amount; the balance of an account, without considering children.<span class="Apple-converted-space">  </span>@item b The cost of a posting; the cost of an account, without its children.<span class="Apple-converted-space">  </span>@item v The market value of a posting, or an account without its children.<span class="Apple-converted-space">  </span>@item g The net gain (market value minus cost basis), for a posting or an account without its children.<span class="Apple-converted-space">  </span>It is the same as @samp{v-b}. ...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Calculated totals</b></p>
+<p class="p2">@subsubsection Calculated totals</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@table @code @item O The total of all postings seen so far, or the total of an account and all its children.<span class="Apple-converted-space">  </span>@item N The total count of postings affecting an account and all its children.<span class="Apple-converted-space">  </span>@item B The total cost of all postings seen so far; the total cost of an account and all its children.<span class="Apple-converted-space">  </span>@item V The market value of all postings seen so far, or of an account and all its children.<span class="Apple-converted-space">  </span>@item G The total net gain (market value minus cost basis), for a series of postings, or an account and its chil...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Functions</b></p>
+<p class="p2">@subsection Functions</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The available one letter functions are:<span class="Apple-converted-space">  </span>@table @code @item - Negates the argument.<span class="Apple-converted-space">  </span>@item U The absolute (unsigned) value of the argument.<span class="Apple-converted-space">  </span>@item S Strips the commodity from the argument.<span class="Apple-converted-space">  </span>@item A The arithmetic mean of the argument; @samp{Ax} is the same as @samp{x/n}.<span class="Apple-converted-space">  </span>@item P The present market value of the argument.<span class="Apple-converted-space">  </span>The syntax @samp{P(x,d)} is supported, which yields the market value at time @samp{d}.<span class="Apple-converted-space">  </span>If no date is given, then the current moment is used. @end table</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Operators</b></p>
+<p class="p2">@subsection Operators</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The binary and ternary operators, in order of precedence, are:<span class="Apple-converted-space">  </span>@enumerate @item @samp{* /} @item @samp{+ -} @item @samp{! &lt; &gt; =} @item @samp{&amp; | ?:} @end enumerate</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Complex expressions</b></p>
+<p class="p2">@subsection Complex expressions</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">More complicated expressions are possible using:<span class="Apple-converted-space">  </span>@table @code @item NUM A plain integer represents a commodity-less amount.<span class="Apple-converted-space">  </span>@item @{AMOUNT@} An amount in braces can be any kind of amount supported by ledger, with or without a commodity.<span class="Apple-converted-space">  </span>Use this for decimal values.<span class="Apple-converted-space">  </span>@item /REGEXP/ @item W/REGEXP/ A regular expression that matches against an account's full name.<span class="Apple-converted-space">  </span>If a posting, this will match against the account affected by the posting.<span class="Apple-converted-space">  </span>@item //REGEXP/ @item p/REGEXP/ A regular expression tha...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• File format</b></p>
+<p class="p2">@section File format</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The ledger file format is quite simple, but also very flexible.<span class="Apple-converted-space">  </span>It supports many options, though typically the user can ignore most of them.<span class="Apple-converted-space">  </span>They are summarized below.<span class="Apple-converted-space">  </span>The initial character of each line determines what the line means, and how it should be interpreted.<span class="Apple-converted-space">  </span>Allowable initial characters are:<span class="Apple-converted-space">  </span>@table @code @item NUMBER A line beginning with a number denotes a transaction.<span class="Apple-converted-space">  </span>It may be followed by any number of lines, each beginning with whitespace, to denote the transaction's account ...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Ledger Tutorial</b></p>
+<p class="p2">@chapter Ledger Tutorial</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">This chapter presents a series of recipes, gradually introducing all of the command-line features of Ledger.<span class="Apple-converted-space">  </span>For the purpose of these examples, assume the environment variable @var{LEDGER} is set to the file @file{sample.dat} (which is included in the distribution), and that the contents of that file are:<span class="Apple-converted-space">  </span>@smallexample = /^Expenses:Books/ <span class="Apple-converted-space">  </span>(Liabilities:Taxes) <span class="Apple-converted-space">            </span>-0.10<span class="Apple-converted-space">  </span>~ Monthly <span class="Apple-converted-space">  </span>Assets:Bank:Checking<span class="Apple-converted-space">          </span>$500.00 <span class="Apple-converted-space">  </span>Income:Salary<span class="Apple-converted-space">  </span>2004/05/01 * Checking balance <span class="Apple-converted-space">  </span>Assets:Bank:Check...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Checking balances</b></p>
+<p class="p2">@section Checking balances</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Ledger has seven basic commands, but by far the most often used are @command{balance} and @command{register}.<span class="Apple-converted-space">  </span>To see a summary balance of all accounts, use:<span class="Apple-converted-space">  </span>@example ledger bal @end example<span class="Apple-converted-space">  </span>@command{bal} is a short-hand for @command{balance}.<span class="Apple-converted-space">  </span>This command prints out the summary totals of the five parent accounts used in @file{sample.dat}:<span class="Apple-converted-space">  </span>@smallexample<span class="Apple-converted-space">            </span>$1,480.00<span class="Apple-converted-space">              </span>50 AAPL<span class="Apple-converted-space">  </span>Assets <span class="Apple-converted-space">          </span>$-2,500.00<span class="Apple-converted-space">  </span>Equity <span class="Apple-converted-space">              </span>$20.00<span class="Apple-converted-space">  </span>Expenses <span class="Apple-converted-space">            </span>$-500.00<span class="Apple-converted-space">  </span>Income<span class="Apple-converted-space">  </span>...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Sub-account balances</b></p>
+<p class="p2">@subsection Sub-account balances</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The totals reported by the balance command are only the topmost parent accounts.<span class="Apple-converted-space">  </span>To see the totals of all child accounts as well, use the @option{-s} option:<span class="Apple-converted-space">  </span>@example ledger --real -B -s bal @end example<span class="Apple-converted-space">  </span>This reports:<span class="Apple-converted-space">  </span>@smallexample<span class="Apple-converted-space">            </span>$2,980.00<span class="Apple-converted-space">  </span>Assets<span class="Apple-converted-space">            </span>$1,480.00<span class="Apple-converted-space">    </span>Bank:Checking<span class="Apple-converted-space">            </span>$1,500.00<span class="Apple-converted-space">    </span>Brokerage <span class="Apple-converted-space">          </span>$-2,500.00<span class="Apple-converted-space">  </span>Equity:Opening Balances <span class="Apple-converted-space">              </span>$20.00<span class="Apple-converted-space">  </span>Expenses:Books <span class="Apple-converted-space">            </span>$-500.00<span class="Apple-converted-space">  </span>Income:Salary @end smallexample<span class="Apple-converted-space">  </span>This shows that the @samp...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Specific account balances</b></p>
+<p class="p2">@subsection Specific account balances</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">While reporting the totals for all accounts can be useful, most often you will want to check the balance of a specific account or accounts. To do this, put one or more account names after the balance command. Since these names are really regular expressions, you can use partial names if you wish:<span class="Apple-converted-space">  </span>@example ledger bal checking @end example<span class="Apple-converted-space">  </span>Reports:<span class="Apple-converted-space">  </span>@smallexample<span class="Apple-converted-space">            </span>$1,480.00<span class="Apple-converted-space">  </span>Assets:Bank:Checking @end smallexample<span class="Apple-converted-space">  </span>Any number of names may be used:<span class="Apple-converted-space">  </span>@example ledger bal checking broker li...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• The register report</b></p>
+<p class="p2">@section The register report</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">While the @command{balance} command can be very handy for checking account totals, by far the most powerful of Ledger's reporting tools is the @command{register} command.<span class="Apple-converted-space">  </span>In fact, internally both commands use the same logic, but report the results differently: @command{balance} shows the summary totals, while @command{register} reports each posting and how it contributes to that total.<span class="Apple-converted-space">  </span>Paradoxically, the most basic form of @command{register} is almost never used, since it displays every postin...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Specific register queries</b></p>
+<p class="p2">@subsection Specific register queries</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The most common use of the register command is to summarize postings based on the account(s) they affect.<span class="Apple-converted-space">  </span>Using @file{sample.dat} as as example, we could look at all book purchases using:<span class="Apple-converted-space">  </span>@example ledger reg books @end example<span class="Apple-converted-space">  </span>Reports:<span class="Apple-converted-space">  </span>@smallexample 2004/05/29 Book Store <span class="Apple-converted-space">          </span>Expenses:Books <span class="Apple-converted-space">              </span>$20.00 <span class="Apple-converted-space">      </span>$20.00 @end smallexample<span class="Apple-converted-space">  </span>If a double-dash (@samp{--}) occurs in the list of regular expressions, any following arguments are matched against payee names, instead of accoun...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Selecting postings</b></p>
+<p class="p2">@section Selecting postings</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Although the easiest way to use the register is to report all the postings affecting a set of accounts, it can often result in more information than you want.<span class="Apple-converted-space">  </span>To cope with an ever-growing amount of data, there are several options which can help you pinpoint your report to epostly the postings that interest you most.<span class="Apple-converted-space">  </span>This is called the ``calculation'' phase of Ledger.<span class="Apple-converted-space">  </span>All of its related options are documented under @option{--help-calc}.</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• By date</b></p>
+<p class="p2">@subsection By date</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@c<span class="Apple-converted-space">  </span>-c, --current<span class="Apple-converted-space">          </span>show only current and past transactions (not future)<span class="Apple-converted-space">  </span>@option{--current}(@option{-c}) displays transactions occurring on or before the current date.<span class="Apple-converted-space">  </span>Any transaction recorded for a future date will be ignored, as if it had not been seen.<span class="Apple-converted-space">  </span>This is useful if you happen to pre-record transactions, but still wish to view your balances in terms of what is available today.<span class="Apple-converted-space">  </span>@c<span class="Apple-converted-space">  </span>-b, --begin DATE <span class="Apple-converted-space">      </span>set report begin date @c<span class="Apple-converted-space">  </span>-e, --end DATE <span class="Apple-converted-space">        </span>set report end date<span class="Apple-converted-space">  </span>@opti...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• By status</b></p>
+<p class="p2">@subsection By status</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">By default, all regular postings are included in each report.<span class="Apple-converted-space">  </span>To limit the report to certain kinds of postings, use one or more of the following options:<span class="Apple-converted-space">  </span>@table @option @item -C, --cleared Consider only cleared postings. @item -U, --uncleared Consider only uncleared and pending postings. @item -R, --real Consider only real (non-virtual) postings. @item -L, --actual Consider only actual (non-automated) postings. @end table<span class="Apple-converted-space">  </span>Cleared postings are indicated by an asterix placed just before the pay...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• By relationship</b></p>
+<p class="p2">@subsection By relationship</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@c<span class="Apple-converted-space">  </span>-r, --related<span class="Apple-converted-space">          </span>calculate report using related postings<span class="Apple-converted-space">  </span>Normally, a register report includes only the postings that match the regular expressions specified after the command word.<span class="Apple-converted-space">  </span>For example, to report all expenses:<span class="Apple-converted-space">  </span>@example ledger reg ^expenses @end example<span class="Apple-converted-space">  </span>This reports:<span class="Apple-converted-space">  </span>@smallexample 2004/05/29 Book Store <span class="Apple-converted-space">          </span>Expenses:Books <span class="Apple-converted-space">              </span>$20.00 <span class="Apple-converted-space">      </span>$20.00 @end smallexample<span class="Apple-converted-space">  </span>Using @option{--related} (@option{-r}) reports the postings that did not match your query, but o...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• By budget</b></p>
+<p class="p2">@subsection By budget</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@c<span class="Apple-converted-space">      </span>--budget <span class="Apple-converted-space">          </span>generate budget transactions based on FILE<span class="Apple-converted-space">  </span>There is more information about budgeting and forecasting in @ref{Budgeting and forecasting}.<span class="Apple-converted-space">  </span>Basically, if you have any period transactions in your ledger file, you can use these options.<span class="Apple-converted-space">  </span>A period transaction looks like:<span class="Apple-converted-space">  </span>@example ~ Monthly <span class="Apple-converted-space">  </span>Assets:Bank:Checking <span class="Apple-converted-space">        </span>$500.00 <span class="Apple-converted-space">  </span>Income:Salary @end example<span class="Apple-converted-space">  </span>The difference from a regular transaction is that the first line begins with a tilde (~), and instead of a payee the...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• By value expression</b></p>
+<p class="p2">@subsection By value expression</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@c<span class="Apple-converted-space">  </span>-l, --limit EXPR <span class="Apple-converted-space">      </span>calculate only postings matching EXPR<span class="Apple-converted-space">  </span>Value expressions can be quite complex, and are treated more fully in @ref{Value expressions}.<span class="Apple-converted-space">  </span>They can be used for limiting a report with @option{--limit} (@option{-l}).<span class="Apple-converted-space">  </span>The following command report income since august, but expenses since october:<span class="Apple-converted-space">  </span>@example ledger -l '(/income/&amp;d&gt;=[aug])|(/expenses/&amp;d&gt;=[oct])' reg @end example<span class="Apple-converted-space">  </span>The basic form of this value expression is @samp{(A&amp;B)|(A&amp;B)}.<span class="Apple-converted-space">  </span>The @samp{A} in each part matches aga...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Massaging register output</b></p>
+<p class="p2">@section Massaging register output</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Even after filtering down your data to just the postings you're interested in, the default reporting method of one posting per line is often still too much.<span class="Apple-converted-space">  </span>To combat this complexity, it is possible to ask Ledger to report the details to you in many different forms, summarized in various ways.<span class="Apple-converted-space">  </span>This is the ``display'' phase of Ledger, and is documented under @option{--help-disp}.</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Summarizing</b></p>
+<p class="p2">@subsection Summarizing</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@c<span class="Apple-converted-space">  </span>-n, --collapse <span class="Apple-converted-space">        </span>register: collapse transactions with multiple postings<span class="Apple-converted-space">  </span>When multiple postings relate to a single transaction, they are reported as part of that transaction.<span class="Apple-converted-space">  </span>For example, in the case of @file{sample.dat}:<span class="Apple-converted-space">  </span>@example ledger reg -- book @end example<span class="Apple-converted-space">  </span>Reports:<span class="Apple-converted-space">  </span>@smallexample 2004/05/29 Book Store <span class="Apple-converted-space">          </span>Expenses:Books <span class="Apple-converted-space">              </span>$20.00 <span class="Apple-converted-space">      </span>$20.00 <span class="Apple-converted-space">                                </span>Liabilities:MasterCard<span class="Apple-converted-space">      </span>$-20.00<span class="Apple-converted-space">            </span>0 <span class="Apple-converted-space">                                </span>(Liabi...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Quick periods</b></p>
+<p class="p2">@subsection Quick periods</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Although the @option{-p} option (also @option{--period}) is much more versatile, there are other options to make the most common period reports easier:<span class="Apple-converted-space">  </span>@table @option @item -W, --weekly Show weekly sub-totals.<span class="Apple-converted-space">  </span>Same as @samp{-p weekly}. @item -M, --monthly Show monthly sub-totals.<span class="Apple-converted-space">  </span>Same as @samp{-p monthly}. @item -Y, --yearly Show yearly sub-totals.<span class="Apple-converted-space">  </span>Same as @samp{-p yearly}. @end table<span class="Apple-converted-space">  </span>@c<span class="Apple-converted-space">      </span>--dow<span class="Apple-converted-space">              </span>show a days-of-the-week report<span class="Apple-converted-space">  </span>There is one kind of period report cannot be don...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Ordering and width</b></p>
+<p class="p2">@subsection Ordering and width</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@c<span class="Apple-converted-space">  </span>-S, --sort EXPR<span class="Apple-converted-space">        </span>sort report according to the value expression EXPR<span class="Apple-converted-space">  </span>The postings displayed in a report are shown in the same order as they appear in the ledger file.<span class="Apple-converted-space">  </span>To change the order and sort a report, use the @option{--sort} option.<span class="Apple-converted-space">  </span>@option{--sort} takes a value expression to determine the value to sort against, making it possible to sort according to complex criteria.<span class="Apple-converted-space">  </span>Here are some simple and useful examples:<span class="Apple-converted-space">  </span>@example ledger --sort d reg ^exp<span class="Apple-converted-space">    </span># sort by date ledger --sort t...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Averages and percentages</b></p>
+<p class="p2">@subsection Averages and percentages</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@c<span class="Apple-converted-space">  </span>-A, --average<span class="Apple-converted-space">          </span>report average posting amount<span class="Apple-converted-space">  </span>To see the running total changed to a running average, use @option{-A}.<span class="Apple-converted-space">  </span>The final posting's total will be the overall average of all displayed postings.<span class="Apple-converted-space">  </span>The works in conjunction with period reporting, so that you can see your monthly average expenses with:<span class="Apple-converted-space">  </span>@example ledger -AM<span class="Apple-converted-space">  </span>reg ^expenses:food ledger -AMn reg ^expenses @end example<span class="Apple-converted-space">  </span>This works in the balance report too:<span class="Apple-converted-space">  </span>@example ledger -AM<span class="Apple-converted-space">  </span>bal ^expenses:food ledger -AMs bal ^expens...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Reporting total data</b></p>
+<p class="p2">@subsection Reporting total data</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@c<span class="Apple-converted-space">      </span>--totals <span class="Apple-converted-space">          </span>in the "xml" report, include running total<span class="Apple-converted-space">  </span>Normally in the @command{xml} report, only posting amounts are printed.<span class="Apple-converted-space">  </span>To include the running total under a @samp{&lt;total&gt;} tag, use @option{--totals}.<span class="Apple-converted-space">  </span>This does not affect any other report.<span class="Apple-converted-space">  </span>@c<span class="Apple-converted-space">  </span>-j, --amount-data<span class="Apple-converted-space">      </span>print only raw amount data (useful for scripting) @c<span class="Apple-converted-space">  </span>-J, --total-data <span class="Apple-converted-space">      </span>print only raw total data<span class="Apple-converted-space">  </span>In the register report only, the output can be changed with @option{-j} to show only the date and the am...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Display by value expression</b></p>
+<p class="p2">@subsection Display by value expression</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@c<span class="Apple-converted-space">  </span>-d, --display EXPR <span class="Apple-converted-space">    </span>display only postings matching EXPR<span class="Apple-converted-space">  </span>With @option{-d} you can decide which postings (or accounts in the balance report) are displayed, according to a value expression.<span class="Apple-converted-space">  </span>The computed total is not affected, only the display.<span class="Apple-converted-space">  </span>This can be very useful for shortening a report without changing the running total:<span class="Apple-converted-space">  </span>@example ledger -d 'd&gt;=[last month]' reg checking @end example<span class="Apple-converted-space">  </span>This command shows the checking account's register, beginning from last month, but with the running ...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Change report format</b></p>
+<p class="p2">@subsection Change report format</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">@c<span class="Apple-converted-space">  </span>-y, --date-format STR<span class="Apple-converted-space">  </span>use STR as the date format (default: %Y/%m/%d)<span class="Apple-converted-space">  </span>When dates are printed in any report, the default format is @samp{%Y/%m/%d}, which yields dates of the form @samp{YYYY/mm/dd}. This can be changed with @option{-y}, whose argument is a @code{strftime} string---see your system's C library documentation for the allowable codes.<span class="Apple-converted-space">  </span>Mostly you will want to use @samp{%Y}, @samp{%m} and @samp{%d}, in whatever combination is convenient for your locale.<span class="Apple-converted-space">  </span>@c<span class="Apple-converted-space">  </span>-F, --format STR <span class="Apple-converted-space">      </span>...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Standard queries</b></p>
+<p class="p2">@section Standard queries</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">If your ledger file uses the standard top-level accounts: Assets, Liabilities, Income, Expenses, Equity: then the following queries will enable you to generate some typical accounting reports from your data.<span class="Apple-converted-space">  </span>Your @emph{net worth} can be determined by balancing assets against liabilities:<span class="Apple-converted-space">  </span>@example ledger bal ^assets ^liab @end example<span class="Apple-converted-space">  </span>By removing long-term investment and loan accounts, you can see your current net liquidity (or liquid net worth):<span class="Apple-converted-space">  </span>@example ledger bal ^assets ^liab -retirement ...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Reporting balance totals</b></p>
+<p class="p2">@section Reporting balance totals</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The balance command prints out the summarized balances of all my top-level accounts, excluding sub-accounts.<span class="Apple-converted-space">  </span>In order to see the balances for a specific account, just specify a regular expression after the balance command:<span class="Apple-converted-space">  </span>@example ledger balance expenses:food @end example<span class="Apple-converted-space">  </span>This will show all the money that's been spent on food, since the beginning of the ledger.<span class="Apple-converted-space">  </span>For food spending just this month (September), use:<span class="Apple-converted-space">  </span>@example ledger -p sep balance expenses:food @end example<span class="Apple-converted-space">  </span>Or maybe you want t...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Reporting percentages</b></p>
+<p class="p2">@section Reporting percentages</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">There is no built-in way to report posting amounts or account balances in terms of percentages.</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Ledger in Practice</b></p>
+<p class="p2">@chapter Ledger in Practice</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Stating where money goes</b></p>
+<p class="p2">@section Stating where money goes</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Accountants will talk of ``credits'' and ``debits'', but the meaning is often different from the layman's understanding.<span class="Apple-converted-space">  </span>To avoid confusion, Ledger uses only subtractions and additions, although the underlying intent is the same as standard accounting principles.<span class="Apple-converted-space">  </span>Recall that every posting will involve two or more accounts. Money is transferred from one or more accounts to one or more other accounts.<span class="Apple-converted-space">  </span>To record the posting, an amount is @emph{subtracted} from the source accounts, and @emph{adde...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Assets and Liabilities</b></p>
+<p class="p2">@section Assets and Liabilities</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Assets are money that you have, and Liabilities are money that you owe.<span class="Apple-converted-space">  </span>``Liabilities'' is just a more inclusive name for Debts.<span class="Apple-converted-space">  </span>An Asset is typically increased by transferring money from an Income account, such as when you get paid.<span class="Apple-converted-space">  </span>Here is a typical transaction:<span class="Apple-converted-space">  </span>@smallexample 2004/09/29<span class="Apple-converted-space">  </span>My Employer <span class="Apple-converted-space">    </span>Assets:Checking <span class="Apple-converted-space">              </span>$500.00 <span class="Apple-converted-space">    </span>Income:Salary @end smallexample<span class="Apple-converted-space">  </span>Money, here, comes from an Income account belonging to ``My Employer'', and is transferred to your checking accoun...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Tracking reimbursable expenses</b></p>
+<p class="p2">@subsection Tracking reimbursable expenses</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Sometimes you will want to spend money on behalf of someone else, which will eventually get repaid.<span class="Apple-converted-space">  </span>Since the money is still ``yours'', it is really an asset.<span class="Apple-converted-space">  </span>And since the expenditure was for someone else, you don't want it contaminating your Expenses reports.<span class="Apple-converted-space">  </span>You will need to keep an account for tracking reimbursements.<span class="Apple-converted-space">  </span>This is fairly easy to do in ledger.<span class="Apple-converted-space">  </span>When spending the money, spend it @emph{to} your Assets:Reimbursements, using a different account for each person or business that you...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Typical queries</b></p>
+<p class="p2">@section Typical queries</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">A query such as the following shows all expenses since last October, sorted by total:<span class="Apple-converted-space">  </span>@example ledger -b "last oct" -s -S T bal ^expenses @end example<span class="Apple-converted-space">  </span>From left to right the options mean: Show transactions since October, 2003; show all sub-accounts; sort by the absolute value of the total; and report the balance for all expenses.</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Reporting monthly expenses</b></p>
+<p class="p2">@subsection Reporting monthly expenses</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The following query makes it easy to see monthly expenses, with each month's expenses sorted by the amount:<span class="Apple-converted-space">  </span>@example ledger -M --period-sort t reg ^expenses @end example<span class="Apple-converted-space">  </span>Now, you might wonder where the money came from to pay for these things.<span class="Apple-converted-space">  </span>To see that report, add @option{-r}, which shows the ``related account'' postings:<span class="Apple-converted-space">  </span>@example ledger -M --period-sort t -r reg ^expenses @end example<span class="Apple-converted-space">  </span>But maybe this prints too much information.<span class="Apple-converted-space">  </span>You might just want to see how much you're spending with yo...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Visualizing with Gnuplot</b></p>
+<p class="p2">@subsection Visualizing with Gnuplot</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">If you have @command{Gnuplot} installed, you can graph any of the above register reports.<span class="Apple-converted-space">  </span>The script to do this is included in the ledger distribution, and is named @file{scripts/report}.<span class="Apple-converted-space">  </span>Install @file{report} anywhere along your @env{PATH}, and then use @command{report} instead of @command{ledger} when doing a register report.<span class="Apple-converted-space">  </span>The only thing to keep in mind is that you must specify @option{-j} or @option{-J} to indicate whether Gnuplot should plot the amount, or the running total.<span class="Apple-converted-space">  </span>For examp...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Typical plots</b></p>
+<p class="p2">@subsubsection Typical plots</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Here are some useful plots:<span class="Apple-converted-space">  </span>@smallexample report -j -M reg ^expenses <span class="Apple-converted-space">        </span># monthly expenses report -J reg checking <span class="Apple-converted-space">            </span># checking account balance report -J reg ^income ^expenses<span class="Apple-converted-space">    </span># cash flow report<span class="Apple-converted-space">  </span># net worth report, ignoring non-$ postings<span class="Apple-converted-space">  </span>report -J -l "Ua&gt;=@{\$0.01@}" reg ^assets ^liab<span class="Apple-converted-space">  </span># net worth report starting last February.<span class="Apple-converted-space">  </span>the use of a display # predicate (-d) is needed, otherwise the balance will start at # zero, and thus the y-axis will not reflect the true balance<span class="Apple-converted-space">  </span>...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Budgeting and forecasting</b></p>
+<p class="p2">@section Budgeting and forecasting</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Budgeting</b></p>
+<p class="p2">@subsection Budgeting</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Keeping a budget allows you to pay closer attention to your income and expenses, by reporting how far your actual financial activity is from your expectations.<span class="Apple-converted-space">  </span>To start keeping a budget, put some period transactions at the top of your ledger file.<span class="Apple-converted-space">  </span>A period transaction is almost identical to a regular transaction, except that it begins with a tilde and has a period expression in place of a payee.<span class="Apple-converted-space">  </span>For example:<span class="Apple-converted-space">  </span>@smallexample ~ Monthly <span class="Apple-converted-space">  </span>Expenses:Rent <span class="Apple-converted-space">              </span>$500.00 <span class="Apple-converted-space">  </span>Expenses:Food <span class="Apple-converted-space">      </span>...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Forecasting</b></p>
+<p class="p2">@subsection Forecasting</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Sometimes it's useful to know what your finances will look like in the future, such as determining when an account will reach zero.<span class="Apple-converted-space">  </span>Ledger makes this easy to do, using the same period transactions as are used for budgeting.<span class="Apple-converted-space">  </span>An example forecast report can be generated with:<span class="Apple-converted-space">  </span>@example ledger --forecast "T&gt;@{\$-500.00@}" register ^assets ^liabilities @end example<span class="Apple-converted-space">  </span>This report continues outputting postings until the running total is greater than $-500.00.<span class="Apple-converted-space">  </span>A final posting is always output, to show...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Commodities and Currencies</b></p>
+<p class="p2">@section Commodities and Currencies</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Ledger makes no assumptions about the commodities you use; it only requires that you specify a commodity.<span class="Apple-converted-space">  </span>The commodity may be any non-numeric string that does not contain a period, comma, forward slash or at-sign.<span class="Apple-converted-space">  </span>It may appear before or after the amount, although it is assumed that symbols appearing before the amount refer to currencies, while non-joined symbols appearing after the amount refer to commodities.<span class="Apple-converted-space">  </span>Here are some valid currency and commodity specifiers:<span class="Apple-converted-space">  </span>@example $20.00 <span class="Apple-converted-space">        </span>;...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Commodity price histories</b></p>
+<p class="p2">@subsection Commodity price histories</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Whenever a commodity is purchased using a different commodity (such as a share of common stock using dollars), it establishes a price for that commodity on that day.<span class="Apple-converted-space">  </span>It is also possible, by recording price details in a ledger file, to specify other prices for commodities at any given time.<span class="Apple-converted-space">  </span>Such price transactions might look like those below:<span class="Apple-converted-space">  </span>@smallexample P 2004/06/21 02:17:58 TWCUX $27.76 P 2004/06/21 02:17:59 AGTHX $25.41 P 2004/06/21 02:18:00 OPTFX $39.31 P 2004/06/21 02:18:01 FEQTX $22.49...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Commodity equivalencies</b></p>
+<p class="p2">@subsection Commodity equivalencies</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Sometimes a commodity has several forms which are all equivalent.<span class="Apple-converted-space">  </span>An example of this is time.<span class="Apple-converted-space">  </span>Whether tracked in terms of minutes, hours or days, it should be possible to convert between the various forms. Doing this requires the use of commodity equivalencies.<span class="Apple-converted-space">  </span>For example, you might have the following two postings, one which transfers an hour of time into a @samp{Billable} account, and another which decreases the same account by ten minutes.<span class="Apple-converted-space">  </span>The resulting report will indicate that fifty min...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Accounts and Inventories</b></p>
+<p class="p2">@section Accounts and Inventories</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Since Ledger's accounts and commodity system is so flexible, you can have accounts that don't really exist, and use commodities that no one else recognizes.<span class="Apple-converted-space">  </span>For example, let's say you are buying and selling various items in EverQuest, and want to keep track of them using a ledger.<span class="Apple-converted-space">  </span>Just add items of whatever quantity you wish into your EverQuest account:<span class="Apple-converted-space">  </span>@smallexample 9/29<span class="Apple-converted-space">  </span>Get some stuff at the Inn <span class="Apple-converted-space">    </span>Places:Black's Tavern <span class="Apple-converted-space">                  </span>-3 Apples <span class="Apple-converted-space">    </span>Places:Black's Tavern<span class="Apple-converted-space">                </span>...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Understanding Equity</b></p>
+<p class="p2">@section Understanding Equity</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The most confusing transaction in any ledger will be your equity account--- because starting balances can't come out of nowhere.<span class="Apple-converted-space">  </span>When you first start your ledger, you will likely already have money in some of your accounts.<span class="Apple-converted-space">  </span>Let's say there's $100 in your checking account; then add a transaction to your ledger to reflect this amount. Where will money come from?<span class="Apple-converted-space">  </span>The answer: your equity.<span class="Apple-converted-space">  </span>@smallexample 10/2<span class="Apple-converted-space">  </span>Opening Balance <span class="Apple-converted-space">    </span>Assets:Checking <span class="Apple-converted-space">                        </span>$100.00 <span class="Apple-converted-space">    </span>Equity:Opening B...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Dealing with Petty Cash</b></p>
+<p class="p2">@section Dealing with Petty Cash</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Something that stops many people from keeping a ledger at all is the insanity of tracking small cash expenses.<span class="Apple-converted-space">  </span>They rarely generate a receipt, and there are often a lot of small postings, rather than a few large ones, as with checks.<span class="Apple-converted-space">  </span>One solution is: don't bother.<span class="Apple-converted-space">  </span>Move your spending to a debit card, but in general ignore cash.<span class="Apple-converted-space">  </span>Once you withdraw it from the ATM, mark it as already spent to an @samp{Expenses:Cash} category:<span class="Apple-converted-space">  </span>@smallexample 2004/03/15 ATM <span class="Apple-converted-space">    </span>Expenses:Cash<span class="Apple-converted-space">                      </span>$...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Working with multiple funds and accounts</b></p>
+<p class="p2">@section Working with multiple funds and accounts</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">There are situations when the accounts you're tracking are different between your clients and the financial institutions where money is kept.<span class="Apple-converted-space">  </span>An example of this is working as the treasurer for a religious institution.<span class="Apple-converted-space">  </span>From the secular point of view, you might be working with three different accounts:<span class="Apple-converted-space">  </span>@itemize @item Checking @item Savings @item Credit Card @end itemize<span class="Apple-converted-space">  </span>From a religious point of view, the community expects to divide its resources into multiple ``funds'', from which it makes pu...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Archiving previous years</b></p>
+<p class="p2">@section Archiving previous years</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">After a while, your ledger can get to be pretty large.<span class="Apple-converted-space">  </span>While this will not slow down the ledger program much---it's designed to process ledger files very quickly---things can start to feel ``messy''; and it's a universal complaint that when finances feel messy, people avoid them.<span class="Apple-converted-space">  </span>Thus, archiving the data from previous years into their own files can offer a sense of completion, and freedom from the past.<span class="Apple-converted-space">  </span>But how to best accomplish this with the ledger program?<span class="Apple-converted-space">  </span>There are two commands that make...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Virtual postings</b></p>
+<p class="p2">@section Virtual postings</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">A virtual posting is when you, in your mind, see money as moving to a certain place, when in reality that money has not moved at all. There are several scenarios in which this type of tracking comes in handy, and each of them will be discussed in detail.<span class="Apple-converted-space">  </span>To enter a virtual posting, surround the account name in parentheses.<span class="Apple-converted-space">  </span>This form of usage does not need to balance.<span class="Apple-converted-space">  </span>However, if you want to ensure the virtual posting balances with other virtual postings in the same transaction, use square bra...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Automated postings</b></p>
+<p class="p2">@section Automated postings</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">As a Bahá'í, I need to compute Huqúqu'lláh whenever I acquire assets. It is similar to tithing for Jews and Christians, or to Zakát for Muslims.<span class="Apple-converted-space">  </span>The epost details of computing Huqúqu'lláh are somewhat complex, but if you have further interest, please consult the Web.<span class="Apple-converted-space">  </span>Ledger makes this otherwise difficult law very easy.<span class="Apple-converted-space">  </span>Just set up an automated posting at the top of your ledger file:<span class="Apple-converted-space">  </span>@smallexample ; This automated transaction will compute Huqúqu'lláh based on this ; journal's postings.<span class="Apple-converted-space">  </span>Any t...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Using Emacs to Keep Your Ledger</b></p>
+<p class="p2">@section Using Emacs to Keep Your Ledger</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">In the Ledger tarball is an Emacs module, @file{ledger.el}.<span class="Apple-converted-space">  </span>This module makes the process of keeping a text ledger much easier for Emacs users.<span class="Apple-converted-space">  </span>I recommend putting this at the top of your ledger file:<span class="Apple-converted-space">  </span>@example ; -*-ledger-*- @end example<span class="Apple-converted-space">  </span>And this in your @file{.emacs} file, after copying @file{ledger.el} to your @file{site-lisp} directory:<span class="Apple-converted-space">  </span>@example (load "ledger") @end example<span class="Apple-converted-space">  </span>Now when you edit your ledger file, it will be in @command{ledger-mode}.<span class="Apple-converted-space">  </span>@command{ledger-mode} adds these command...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Using GnuCash to Keep Your Ledger</b></p>
+<p class="p2">@section Using GnuCash to Keep Your Ledger</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The Ledger tool is fast and simple, but it offers no custom method for actually editing the ledger.<span class="Apple-converted-space">  </span>It assumes you know how to use a text editor, and like doing so.<span class="Apple-converted-space">  </span>There is, at least, an Emacs mode that makes editing Ledger's data files much easier.<span class="Apple-converted-space">  </span>You are also free to use GnuCash to maintain your ledger, and the Ledger program for querying and reporting on the contents of that ledger.<span class="Apple-converted-space">  </span>It takes a little longer to parse the XML data format that GnuCash uses, but the end result is identical....</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Using timeclock to record billable time</b></p>
+<p class="p2">@section Using timeclock to record billable time</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The timeclock tool makes it easy to track time events, like clocking into and out of a particular job.<span class="Apple-converted-space">  </span>These events accumulate in a timelog file.<span class="Apple-converted-space">  </span>Each in/out event may have an optional description.<span class="Apple-converted-space">  </span>If the ``in'' description is a ledger account name, these in/out pairs may be viewed as virtual postings, adding time commodities (hours) to that account.<span class="Apple-converted-space">  </span>For example, the command-line version of the timeclock tool could be used to begin a timelog file like:<span class="Apple-converted-space">  </span>@example export TIMELOG=$HOME/.timelog...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Using XML</b></p>
+<p class="p2">@section Using XML</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">By default, Ledger uses a human-readable data format, and displays its reports in a manner meant to be read on screen.<span class="Apple-converted-space">  </span>For the purpose of writing tools which use Ledger, however, it is possible to read and display data using XML.<span class="Apple-converted-space">  </span>This section documents that format.<span class="Apple-converted-space">  </span>The general format used for Ledger data is:<span class="Apple-converted-space">  </span>@smallexample &lt;?xml version="1.0"?&gt; &lt;ledger&gt; <span class="Apple-converted-space">  </span>&lt;xact&gt;...&lt;/xact&gt; <span class="Apple-converted-space">  </span>&lt;xact&gt;...&lt;/xact&gt; <span class="Apple-converted-space">  </span>&lt;xact&gt;...&lt;/xact&gt;... &lt;/ledger&gt; @end smallexample<span class="Apple-converted-space">  </span>The data stream is enclosed in a @samp{ledger} tag, ...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Random things</b></p>
+<p class="p2">@chapter Random things</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Whenever a commodity is exchanged for another in a posting, one of the two is considered @emph{primary}, and the other secondary. Primariness of a commodity is remembered, since the @option{--market} option only renders balances into secondary commodities, never primaries.<span class="Apple-converted-space">  </span>To render primaries, use the @option{--exchange=COMMODITY} option.<span class="Apple-converted-space">  </span>In all of the following examples, the P commodity is considered primary and the S is secondary (the P at the beginning of the line indicates a price-setting ...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Anatomy of a journal file</b></p>
+<p class="p2">@chapter Anatomy of a journal file</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Everything begins with a journal file---the anatomy of which is covered in detail in chapter one.<span class="Apple-converted-space">  </span>To review: a @emph{journal} contains one or more @emph{transactions}, each of which refers to two or more @emph{postings}.<span class="Apple-converted-space">  </span>A @emph{posting} specifies that a given @emph{amount} is added to, or subtracted from, an @emph{account}. (@emph{Accounts} may be nested hierarchically by separating the elements using a colon).<span class="Apple-converted-space">  </span>Lastly, an @emph{amount} is a figure representing a given @emph{quantity} of a @e...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Example accounting practices</b></p>
+<p class="p2">@chapter Example accounting practices</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Generating useful reports</b></p>
+<p class="p2">@chapter Generating useful reports</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Once you have a journal file representing a recent history of your finances, the next step is to generate reports in order to give richer meaning to this data.<span class="Apple-converted-space">  </span>For example: Where do you spend your money?<span class="Apple-converted-space">  </span>Do you have enough to cover upcoming expenses?<span class="Apple-converted-space">  </span>Are you creating or losing net worth?<span class="Apple-converted-space">  </span>Are your investment performing well?<span class="Apple-converted-space">  </span>All of these questions can be answered easily with Ledger---if you know how to ask them.<span class="Apple-converted-space">  </span>Preparing complex reports is not a simple task, but neither is it a difficult o...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Value expressions</b></p>
+<p class="p2">@chapter Value expressions</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Format strings</b></p>
+<p class="p2">@chapter Format strings</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Scripting in Python</b></p>
+<p class="p2">@chapter Scripting in Python</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">Ledger is, at heart, just a sophisticated calculator.<span class="Apple-converted-space">  </span>In addition to summing values within “accountsâ€, it guarantees that every transaction balances to zero to confirm these values are correctly transferred between accounts.<span class="Apple-converted-space">  </span>In addition to using this calculator from the command-line to generate reports, you may also access it from the Python scripting language, in order to manipulate the figures however you wish.<span class="Apple-converted-space">  </span>The following chapter presents the ideas you will need to know to accomplish thi...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Creating a session</b></p>
+<p class="p2">@section Creating a session</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">All interactions with the Ledger library take place in the context of a @var{Session}.<span class="Apple-converted-space">  </span>You may create as many sessions as you like, though typically only one is needed during the lifetime of a scriptAn example where more might be needed is a GUI program that opens multiple Ledger files in different windows, and creates reports for each file separately.<span class="Apple-converted-space">  </span>Ledger provides a pre-initialized session named @var{session}, but others can still be created.<span class="Apple-converted-space">  </span>Creating a session is trivial, but before it m...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Initialize a session</b></p>
+<p class="p2">Example of creating a session, reading some journal data, and generating a simplistic report.</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• The design of Ledger</b></p>
+<p class="p2">@chapter The design of Ledger</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The following sections discuss how Ledger is architected, from the ground up, and will show how to use the various parts of the Ledger library from your own scripts.<span class="Apple-converted-space">  </span>Ledger essentially follows five steps in reporting data to the user:<span class="Apple-converted-space">  </span>@enumerate @item Parse journal file into an internal representation @item Perform any implied math within the journal file @item ``Face'' this internal representation as a virtual document @item Apply a series of transforms to the virtual document @item Display t...</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Numerics</b></p>
+<p class="p2">@section Numerics</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Basic amounts</b></p>
+<p class="p2">@subsection Basic amounts</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">The most fundamental type in Ledger is the amount, which may or may not have a commodity attached to it.<span class="Apple-converted-space">  </span>First, we'll deal with the bare case, just to show how the amount type works.<span class="Apple-converted-space">  </span>In C++, most all of Ledger's internal types end in @code{_t}; in Python, the same type name is used, but the @code{_t} suffix is dropped.<span class="Apple-converted-space">  </span>Examples of usage in both languages will be presented throughout.<span class="Apple-converted-space">  </span>amount_t commodity_t updater_t datetime_t balance_t balance_pair_t value_t valexpr_t format_t mask_t</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Journal Representation</b></p>
+<p class="p2">@section Journal Representation</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Content</b></p>
+<p class="p2">journal_t account_t xact_t post_t parser_t</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Reporting</b></p>
+<p class="p2">@section Reporting</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• Terminal Interface</b></p>
+<p class="p2">@section Terminal Interface</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• General Utility</b></p>
+<p class="p2">@section General Utility</p>
+<p class="p3"><br></p>
+<p class="p1"><b>• End Matter</b></p>
+<p class="p2">@bye</p>
+<p class="p3"><br></p>
+</body>
+</html>
diff --git a/doc/Ledger.scriv/QuickLook/Thumbnail.jpg b/doc/Ledger.scriv/QuickLook/Thumbnail.jpg
new file mode 100644
index 00000000..e4764531
--- /dev/null
+++ b/doc/Ledger.scriv/QuickLook/Thumbnail.jpg
Binary files differ
diff --git a/doc/Ledger.scriv/binder.scrivproj b/doc/Ledger.scriv/binder.scrivproj
new file mode 100644
index 00000000..d5d7401f
--- /dev/null
+++ b/doc/Ledger.scriv/binder.scrivproj
@@ -0,0 +1,34782 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1866</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1874</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1882</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1865</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1862</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1864</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1863</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Draft</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>BinderID</string>
+ <integer>0</integer>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableDictionary</string>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableDictionary</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>78</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>99</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>119</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>663</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1127</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1611</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1632</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1652</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1662</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1682</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1691</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1700</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1752</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1851</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Front Matter</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>4</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Content</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>5</integer>
+ <integer>1</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380198.488671</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377075.95730999</real>
+ </dict>
+ <string>{0, 0}</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>SCRBinderDocument</string>
+ <string>KBBaseNode</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>SCRBinderDocument</string>
+ </dict>
+ <integer>15</integer>
+ <integer>3</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379872.725806</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377038.37691599</real>
+ </dict>
+ <string>{132, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>40</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>76</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>73</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>75</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>38</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>74</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>77</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>72</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Introduction</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>39</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>6</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>41</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>51</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>44</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>49</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>46</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>48</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>42</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>47</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>50</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>45</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>43</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>7</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380205.108419</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377112.78556299</real>
+ </dict>
+ <string>{5795, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>55</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>70</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>67</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>69</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>53</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>68</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>71</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>52</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>66</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>More introduction</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>54</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>8</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>56</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>59</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>64</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>61</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>63</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>57</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>62</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>65</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>60</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>58</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>9</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380206.90917</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377167.49251801</real>
+ </dict>
+ <string>{2186, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379880.19667</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377138.15110201</real>
+ </dict>
+ <string>{26, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379841.887961</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377102.50709599</real>
+ </dict>
+ <string>{21, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>82</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>97</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>94</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>96</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>80</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>95</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>98</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>79</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>93</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Building the program</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>81</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>12</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>83</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>86</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>91</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>88</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>90</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>84</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>89</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>92</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>87</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>85</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>14</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380208.55156901</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377214.207609</real>
+ </dict>
+ <string>{397, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379843.63358599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377190.90649301</real>
+ </dict>
+ <string>{29, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>103</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>118</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>115</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>117</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>101</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>116</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>77</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>100</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>114</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Getting help</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>102</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>13</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>104</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>107</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>112</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>109</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>111</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>105</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>110</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>113</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>108</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>106</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380210.285101</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377223.43095401</real>
+ </dict>
+ <string>{307, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379845.61654699</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377191.06469899</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>123</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>661</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>658</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>660</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>121</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>659</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>662</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>120</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>657</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Quick Reference</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>122</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>16</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>124</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>134</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>329</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>454</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>475</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>496</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>637</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>127</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>132</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>129</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>131</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>125</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>130</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>133</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>128</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>126</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>126</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380212.28033799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377968.001443</real>
+ </dict>
+ <string>{1460, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>138</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>328</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>325</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>327</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>136</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>326</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>200</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>135</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>324</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Commands</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>137</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>28</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>139</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>159</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>180</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>201</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>222</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>243</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>263</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>283</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>303</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>143</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>157</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>154</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>156</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>141</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>155</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>158</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>140</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>153</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>balance</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>142</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>44</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>144</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>147</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>152</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>149</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>151</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>145</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>150</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>148</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>146</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>128</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380225.281611</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378005.88293701</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379967.09079501</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377575.76897499</real>
+ </dict>
+ <string>{19, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>163</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>178</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>175</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>177</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>161</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>176</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>179</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>160</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>174</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>register</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>162</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>54</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>164</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>167</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>172</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>169</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>171</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>165</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>170</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>173</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>168</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>166</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>129</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380226.97803399</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378030.22547999</real>
+ </dict>
+ <string>{941, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379969.39724201</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377604.24554199</real>
+ </dict>
+ <string>{20, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>184</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>199</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>196</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>198</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>182</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>197</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>200</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>181</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>195</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>print</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>183</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>55</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>185</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>188</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>193</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>190</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>192</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>186</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>191</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>194</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>189</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>187</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>130</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380228.64144599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378044.479743</real>
+ </dict>
+ <string>{442, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379970.98177701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377606.845447</real>
+ </dict>
+ <string>{17, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>205</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>220</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>217</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>219</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>203</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>218</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>221</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>202</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>216</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>output</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>204</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>56</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>206</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>209</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>214</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>211</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>213</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>207</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>212</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>215</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>210</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>208</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>131</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380230.308256</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378055.630086</real>
+ </dict>
+ <string>{494, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379972.840294</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377607.72544301</real>
+ </dict>
+ <string>{18, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>226</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>241</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>238</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>240</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>224</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>239</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>242</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>223</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>237</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>xml</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>225</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>57</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>227</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>230</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>235</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>232</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>234</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>228</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>233</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>236</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>231</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>229</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>132</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380231.85143399</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378066.77267799</real>
+ </dict>
+ <string>{252, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379975.65133101</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377608.75711799</real>
+ </dict>
+ <string>{15, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>247</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>262</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>259</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>261</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>245</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>260</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>200</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>244</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>258</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>emacs</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>246</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>58</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>248</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>251</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>256</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>253</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>255</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>249</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>254</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>257</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>252</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>250</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>133</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380234.86124599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378083.17862701</real>
+ </dict>
+ <string>{269, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379990.286814</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377609.381001</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>267</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>282</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>279</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>281</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>265</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>280</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>221</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>264</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>278</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>equity</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>266</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>59</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>268</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>271</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>276</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>273</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>275</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>269</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>274</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>277</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>272</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>270</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>134</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380236.72378799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378099.58455199</real>
+ </dict>
+ <string>{203, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379991.78393999</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377610.220999</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>287</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>302</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>299</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>301</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>285</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>300</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>221</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>284</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>298</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>prices</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>286</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>60</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>288</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>291</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>296</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>293</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>295</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>289</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>294</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>297</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>292</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>290</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>135</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380238.49103799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378117.28630701</real>
+ </dict>
+ <string>{385, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379993.063196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377611.39712501</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>307</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>322</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>319</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>321</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>305</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>320</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>323</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>304</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>318</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>xact</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>306</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>61</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>308</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>311</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>316</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>313</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>315</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>309</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>314</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>317</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>312</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>310</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>136</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380240.304575</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378128.54081401</real>
+ </dict>
+ <string>{1844, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379994.726697</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377612.844621</real>
+ </dict>
+ <string>{16, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379884.23462701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377508.11287999</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>333</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>453</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>450</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>452</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>331</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>451</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>323</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>330</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>449</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Options</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>332</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>29</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>334</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>344</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>365</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>386</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>407</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>428</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>337</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>342</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>339</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>341</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>335</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>340</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>343</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>338</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>336</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>137</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380242.03308901</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378144.34700701</real>
+ </dict>
+ <string>{643, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>348</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>363</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>360</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>362</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>346</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>361</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>364</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>345</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>359</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Basic options</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>347</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>62</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>349</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>352</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>357</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>354</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>356</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>350</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>355</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>358</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>353</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>351</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>138</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380246.153671</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378161.576599</real>
+ </dict>
+ <string>{2163, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379998.70221999</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377619.196078</real>
+ </dict>
+ <string>{25, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>369</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>384</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>381</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>383</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>367</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>382</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>385</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>366</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>380</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Report filtering</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>368</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>63</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>370</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>373</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>378</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>375</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>377</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>371</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>376</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>379</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>374</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>372</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>139</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380248.219491</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378171.25561699</real>
+ </dict>
+ <string>{4001, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380000.14838001</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377626.427136</real>
+ </dict>
+ <string>{28, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>390</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>405</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>402</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>404</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>388</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>403</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>406</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>387</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>401</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Output customization</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>389</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>64</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>391</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>394</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>399</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>396</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>398</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>392</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>397</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>400</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>395</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>393</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>140</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380250.66079599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378172.59122801</real>
+ </dict>
+ <string>{5218, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380002.80918601</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377629.13886499</real>
+ </dict>
+ <string>{32, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>411</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>426</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>423</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>425</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>409</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>424</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>427</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>408</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>422</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Commodity reporting</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>410</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>65</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>412</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>415</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>420</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>417</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>419</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>413</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>418</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>421</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>416</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>414</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>141</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380253.990666</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378173.795993</real>
+ </dict>
+ <string>{1906, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380004.67183501</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377631.64243901</real>
+ </dict>
+ <string>{31, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>432</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>447</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>444</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>446</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>430</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>445</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>448</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>429</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>443</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Environment variables</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>431</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>66</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>433</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>436</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>441</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>438</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>440</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>434</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>439</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>442</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>437</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>435</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>142</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380255.616373</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378175.00711599</real>
+ </dict>
+ <string>{526, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380006.20349899</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377634.130254</real>
+ </dict>
+ <string>{33, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379886.09653801</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377509.03271401</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>458</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>473</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>470</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>472</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>456</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>471</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>474</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>455</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>469</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Period expressions</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>457</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>30</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>459</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>462</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>467</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>464</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>466</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>460</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>465</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>468</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>463</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>461</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>143</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380257.19648299</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378320.36616701</real>
+ </dict>
+ <string>{1363, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379887.922189</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377509.29655299</real>
+ </dict>
+ <string>{27, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>479</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>494</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>491</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>493</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>477</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>492</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>495</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>476</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>490</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Format strings</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>478</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>31</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>480</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>483</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>488</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>485</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>487</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>481</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>486</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>489</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>484</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>482</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>144</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380258.99698099</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378348.29889899</real>
+ </dict>
+ <string>{5169, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379889.78959599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377509.60849601</real>
+ </dict>
+ <string>{23, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>500</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>636</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>633</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>635</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>498</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>634</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>71</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>497</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>632</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Value expressions</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>499</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>32</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>501</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>511</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>572</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>592</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>612</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>504</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>509</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>506</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>508</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>502</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>507</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>510</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>505</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>503</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>145</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380260.693436</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378358.49763399</real>
+ </dict>
+ <string>{1679, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>515</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>571</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>568</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>570</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>513</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>569</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>77</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>512</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>567</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Variables</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>514</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>67</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>516</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>526</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>547</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>519</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>524</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>521</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>523</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>517</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>522</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>525</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>520</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>518</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>146</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380262.718952</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378373.34353101</real>
+ </dict>
+ <string>{979, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>530</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>545</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>542</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>544</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>528</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>543</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>546</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>527</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>541</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Posting/account details</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>529</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>72</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>531</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>534</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>539</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>536</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>538</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>532</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>537</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>540</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>535</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>533</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>147</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380264.68103099</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378380.20667201</real>
+ </dict>
+ <string>{863, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380094.60009599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377662.974953</real>
+ </dict>
+ <string>{38, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>551</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>566</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>563</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>565</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>549</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>564</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>406</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>548</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>562</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Calculated totals</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>550</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>73</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>552</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>555</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>560</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>557</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>559</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>553</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>558</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>561</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>556</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>554</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>148</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380268.27263299</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378382.374374</real>
+ </dict>
+ <string>{547, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380096.596187</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377667.04634699</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380009.63153601</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377638.82568699</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>576</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>591</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>588</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>590</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>574</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>589</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>77</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>573</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>587</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Functions</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>575</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>69</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>577</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>580</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>585</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>582</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>584</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>578</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>583</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>586</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>581</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>579</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>149</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380270.10657099</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378390.99709001</real>
+ </dict>
+ <string>{476, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380011.77327901</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377652.88810799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>596</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>611</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>608</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>610</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>594</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>609</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>77</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>593</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>607</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Operators</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>595</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>70</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>597</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>600</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>605</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>602</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>604</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>598</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>603</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>606</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>601</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>599</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>150</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380271.94841301</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378392.484947</real>
+ </dict>
+ <string>{164, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380013.78536299</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377654.91985101</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>616</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>631</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>628</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>630</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>614</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>629</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>427</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>613</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>627</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Complex expressions</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>615</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>71</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>617</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>620</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>625</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>622</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>624</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>618</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>623</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>626</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>621</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>619</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>151</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380273.932614</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378394.12476099</real>
+ </dict>
+ <string>{1264, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380015.79760101</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377656.623503</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379891.786874</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377509.97595701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>641</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>656</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>653</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>655</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>639</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>654</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>179</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>638</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>652</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>File format</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>640</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>33</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>642</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>645</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>650</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>647</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>649</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>643</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>648</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>651</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>646</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>644</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>152</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380275.77327299</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378493.99847999</real>
+ </dict>
+ <string>{4620, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379895.52266699</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377510.41690299</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379847.39264199</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377346.738444</real>
+ </dict>
+ <string>{24, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>667</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1126</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1123</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1125</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>665</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1124</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>662</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>664</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1122</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Ledger Tutorial</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>666</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>17</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>668</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>678</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>739</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>779</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>898</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1062</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1082</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1102</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>671</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>676</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>673</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>675</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>669</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>674</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>677</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>672</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>670</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>153</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380277.38637999</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378566.58880699</real>
+ </dict>
+ <string>{1213, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>682</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>738</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>735</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>737</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>680</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>736</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>71</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>679</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>734</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Checking balances</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>681</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>74</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>683</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>693</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>713</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>686</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>691</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>688</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>690</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>684</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>689</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>692</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>687</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>685</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>155</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380278.98300901</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378577.77924901</real>
+ </dict>
+ <string>{2831, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>697</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>712</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>709</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>711</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>695</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>710</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>406</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>694</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>708</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Sub-account balances</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>696</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>81</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>698</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>701</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>706</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>703</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>705</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>699</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>704</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>707</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>702</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>700</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>156</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380282.081853</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378587.42607599</real>
+ </dict>
+ <string>{1640, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380020.37534001</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377750.412534</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>717</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>732</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>729</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>731</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>715</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>730</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>733</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>714</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>728</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Specific account balances</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>716</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>82</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>718</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>721</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>726</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>723</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>725</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>719</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>724</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>727</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>722</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>720</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>157</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380283.71019301</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378589.18568</real>
+ </dict>
+ <string>{1031, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380022.20626599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377754.51600599</real>
+ </dict>
+ <string>{37, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379898.905691</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377721.40789601</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>743</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>778</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>775</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>777</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>741</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>776</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>385</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>740</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>774</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>The register report</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>742</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>75</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>744</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>754</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>747</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>752</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>749</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>751</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>745</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>750</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>753</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>748</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>746</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>158</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380285.14162201</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378590.825611</real>
+ </dict>
+ <string>{3459, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>758</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>773</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>770</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>772</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>756</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>771</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>733</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>755</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>769</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Specific register queries</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>757</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>83</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>759</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>762</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>767</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>764</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>766</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>760</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>765</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>768</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>763</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>761</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>159</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380286.639218</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378595.08897299</real>
+ </dict>
+ <string>{869, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380024.91325501</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377763.57890201</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379900.86488599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377727.74311799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>783</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>897</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>894</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>896</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>781</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>895</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>474</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>780</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>893</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Selecting postings</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>782</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>76</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>784</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>793</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>813</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>833</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>853</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>873</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>787</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>792</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>789</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>791</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>785</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>790</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>194</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>788</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>786</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>160</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380288.43032101</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378607.53506199</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>797</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>812</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>809</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>811</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>795</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>810</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>158</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>794</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>808</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>By date</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>796</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>84</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>798</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>801</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>806</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>803</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>805</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>799</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>804</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>807</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>802</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>800</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>161</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380291.25749701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378612.294929</real>
+ </dict>
+ <string>{3091, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380029.389718</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377770.041953</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>817</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>832</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>829</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>831</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>815</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>830</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>77</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>814</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>828</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>By status</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>816</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>85</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>818</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>821</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>826</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>823</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>825</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>819</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>824</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>827</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>822</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>820</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>162</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380293.119874</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378614.062365</real>
+ </dict>
+ <string>{1689, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380031.01949599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377777.02528599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>837</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>852</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>849</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>851</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>835</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>850</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>474</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>834</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>848</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>By relationship</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>836</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>86</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>838</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>841</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>846</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>843</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>845</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>839</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>844</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>847</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>842</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>840</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>164</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380295.900765</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378617.34822801</real>
+ </dict>
+ <string>{795, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380034.36280799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377779.77690101</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>857</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>872</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>869</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>871</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>855</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>870</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>77</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>854</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>868</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>By budget</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>856</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>87</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>858</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>861</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>866</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>863</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>865</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>859</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>864</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>867</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>862</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>860</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>165</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380297.381448</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378622.34119901</real>
+ </dict>
+ <string>{3733, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380036.087791</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377782.76847401</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>877</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>892</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>889</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>891</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>875</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>890</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>427</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>874</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>888</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>By value expression</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>876</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>88</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>878</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>881</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>886</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>883</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>885</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>879</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>884</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>887</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>882</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>880</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>166</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380299.44395399</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378623.89291599</real>
+ </dict>
+ <string>{1426, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380037.56838799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377785.224204</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379902.69006899</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377730.933891</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>902</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1060</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1057</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1059</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>900</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1058</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1061</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>899</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1056</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Massaging register output</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>901</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>77</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>903</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>913</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>933</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>953</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>974</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>995</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1015</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1036</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>906</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>911</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>908</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>910</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>904</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>909</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>912</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>907</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>905</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>168</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380301.15708399</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378627.40369001</real>
+ </dict>
+ <string>{383, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>917</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>932</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>929</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>931</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>915</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>930</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>495</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>914</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>928</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Summarizing</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>916</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>89</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>918</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>921</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>926</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>923</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>925</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>919</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>924</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>927</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>922</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>920</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>169</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380304.66580799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378636.88346699</real>
+ </dict>
+ <string>{3650, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380040.066185</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377789.38393801</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>937</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>952</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>949</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>951</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>935</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>950</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>364</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>934</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>948</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Quick periods</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>936</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>90</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>938</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>941</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>946</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>943</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>945</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>939</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>944</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>947</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>942</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>940</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>170</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380306.29589501</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378638.426943</real>
+ </dict>
+ <string>{973, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380042.274809</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377797.534789</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>957</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>972</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>969</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>971</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>955</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>970</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>973</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>954</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>968</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Ordering and width</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>956</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>91</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>958</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>961</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>966</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>963</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>965</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>959</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>964</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>967</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>962</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>960</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>171</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380308.18752199</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378640.53058699</real>
+ </dict>
+ <string>{2154, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380043.95886901</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377800.23833001</real>
+ </dict>
+ <string>{30, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>978</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>993</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>990</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>992</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>976</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>991</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>994</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>975</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>989</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Averages and percentages</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>977</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>92</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>979</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>982</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>987</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>984</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>986</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>980</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>985</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>988</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>983</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>981</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>172</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380309.95491999</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378642.650332</real>
+ </dict>
+ <string>{1295, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380045.55056</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377803.10194999</real>
+ </dict>
+ <string>{36, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>999</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1014</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1011</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1013</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>997</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1012</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>406</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>996</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1010</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Reporting total data</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>998</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>93</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1000</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1003</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1008</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1005</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1007</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1001</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1006</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1009</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1004</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1002</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>173</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380311.613455</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378644.45822299</real>
+ </dict>
+ <string>{725, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380046.96426001</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377806.06160501</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1019</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1034</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1031</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1033</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1017</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1032</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1035</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1016</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1030</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Display by value expression</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1018</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>94</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1020</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1023</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1028</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1025</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1027</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1021</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1026</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1029</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1024</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1022</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>174</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380313.475925</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378646.145917</real>
+ </dict>
+ <string>{551, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380048.56085399</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377809.69310501</real>
+ </dict>
+ <string>{39, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1040</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1055</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1052</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1054</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1038</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1053</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>406</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1037</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1051</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Change report format</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1039</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>95</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1041</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1044</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1049</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1046</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1048</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1042</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1047</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1050</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1045</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1043</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>175</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380315.25629899</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378648.08164999</real>
+ </dict>
+ <string>{2236, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380050.29044399</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377812.48557699</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379904.56979701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377734.75018799</real>
+ </dict>
+ <string>{34, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1066</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1081</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1078</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1080</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1064</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1079</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>364</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1063</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1077</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Standard queries</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1065</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>78</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1067</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1070</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1075</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1072</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1074</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1068</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1073</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1076</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1071</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1069</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>176</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380318.28194499</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378650.97754601</real>
+ </dict>
+ <string>{1107, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379906.386904</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377738.58978099</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1086</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1101</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1098</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1100</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1084</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1099</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>448</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1083</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1097</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Reporting balance totals</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1085</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>79</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1087</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1090</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1095</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1092</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1094</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1088</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1093</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1096</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1091</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1089</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>177</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380320.03293401</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378652.54508099</real>
+ </dict>
+ <string>{843, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379909.48016101</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377741.485526</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1106</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1121</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1118</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1120</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1104</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1119</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>973</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1103</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1117</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Reporting percentages</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1105</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>80</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1107</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1110</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1115</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1112</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1114</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1108</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1113</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1116</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1111</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1109</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>178</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380321.59681001</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378654.16095999</real>
+ </dict>
+ <string>{95, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379911.55441701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377744.00531599</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379849.238464</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377346.91453201</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1131</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1610</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1607</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1609</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1129</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1608</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>474</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1128</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1606</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Ledger in Practice</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1130</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>18</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1132</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1152</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1193</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1273</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1322</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1383</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1403</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1423</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1443</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1464</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1484</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1504</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1524</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1545</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1565</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1586</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1136</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1151</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1148</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1150</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1134</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1149</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>448</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1133</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1147</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Stating where money goes</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1135</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>96</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1137</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1140</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1145</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1142</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1144</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1138</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1143</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1146</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1141</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1139</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>180</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380325.37177399</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378662.71155599</real>
+ </dict>
+ <string>{2480, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379915.68355301</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377825.179492</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1156</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1192</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1189</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1191</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1154</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1190</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>427</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1153</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1188</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Assets and Liabilities</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1155</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>97</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1157</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1167</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1160</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1165</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1162</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1164</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1158</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1163</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1166</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1161</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1159</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>181</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380328.87581301</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378664.279154</real>
+ </dict>
+ <string>{2193, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1171</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1186</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1183</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1185</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1169</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1184</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1187</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1168</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1182</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Tracking reimbursable expenses</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1170</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>98</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1172</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1175</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1180</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1177</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1179</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1173</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1178</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1181</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1176</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1174</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>182</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380330.610957</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378668.839118</real>
+ </dict>
+ <string>{5856, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380054.768987</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377833.30642399</real>
+ </dict>
+ <string>{42, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379917.28051499</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377830.33870101</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1197</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1272</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1269</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1271</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1195</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1270</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>662</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1194</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1268</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Typical queries</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1196</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>99</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1198</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1208</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1228</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1201</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1206</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1203</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1205</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1199</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1204</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1207</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1202</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1200</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>183</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380332.20225599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378671.334553</real>
+ </dict>
+ <string>{333, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1212</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1227</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1224</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1226</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1210</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1225</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>546</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1209</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1223</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Reporting monthly expenses</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1211</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>100</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1213</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1216</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1221</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1218</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1220</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1214</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1219</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1222</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1217</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1215</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>184</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380334.01606199</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378675.65383199</real>
+ </dict>
+ <string>{1313, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380057.263816</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377843.00913501</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1232</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1267</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1264</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1266</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1230</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1265</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>994</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1229</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1263</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Visualizing with Gnuplot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1231</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>101</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1233</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1243</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1236</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1241</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1238</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1240</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1234</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1239</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1242</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1237</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1235</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>186</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380335.99869901</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378679.71724099</real>
+ </dict>
+ <string>{865, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1247</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1262</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1259</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1261</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1245</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1260</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>385</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1244</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1258</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Typical plots</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1246</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>102</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1248</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1251</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1256</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1253</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1255</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1249</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1254</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1257</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1252</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1250</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>185</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380337.81104901</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378677.26166099</real>
+ </dict>
+ <string>{1020, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380106.38778299</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377850.920118</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380059.08847201</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377847.84039301</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379921.46663201</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377839.50556499</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1277</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1321</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1318</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1320</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1275</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1319</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1061</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1274</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1317</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Budgeting and forecasting</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1276</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>103</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1278</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1298</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1282</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1297</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1294</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1296</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1280</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1295</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>77</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1279</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1293</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Budgeting</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1281</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>104</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1283</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1286</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1291</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1288</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1290</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1284</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1289</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1292</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1287</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1285</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>188</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380340.288856</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378703.97769499</real>
+ </dict>
+ <string>{1872, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380061.85351399</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377860.39911401</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1302</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1316</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1313</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1315</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1300</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1314</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>495</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1299</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1312</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Forecasting</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1301</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>105</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1303</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1306</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1311</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1308</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1310</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1304</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1309</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1009</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1307</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1305</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>189</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380341.997852</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378705.68173301</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380063.69902301</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377863.638567</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379922.784933</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377857.04743001</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1326</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1382</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1379</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1381</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1324</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1380</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1377</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1323</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1378</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Commodities and Currencies</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1325</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>106</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1327</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1337</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1357</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1330</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1335</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1332</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1334</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1328</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1333</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1336</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1331</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1329</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>190</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380344.742089</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378707.22553301</real>
+ </dict>
+ <string>{3274, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1341</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1356</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1353</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1355</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1339</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1354</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>733</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1338</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1352</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Commodity price histories</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1340</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>107</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1342</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1345</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1350</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1347</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1349</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1343</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1348</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1351</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1346</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1344</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>191</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380346.42616501</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378712.01694301</real>
+ </dict>
+ <string>{832, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380066.311234</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377872.093263</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1361</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1376</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1373</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1375</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1359</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1374</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1377</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1358</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1372</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Commodity equivalencies</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1360</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>108</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1362</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1365</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1370</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1367</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1369</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1363</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1368</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1371</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1366</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1364</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>192</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380348.10139701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378713.896608</real>
+ </dict>
+ <string>{1859, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380068.26857701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377877.26093501</real>
+ </dict>
+ <string>{35, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379924.33101699</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377869.20562401</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1387</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1402</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1399</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1401</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1385</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1400</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>448</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1384</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1398</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Accounts and Inventories</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1386</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>109</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1388</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1391</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1396</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1393</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1395</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1389</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1394</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1397</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1392</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1390</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>193</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380349.65307301</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378716.16824201</real>
+ </dict>
+ <string>{1435, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379928.00795799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377882.74036601</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1407</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1422</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1419</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1421</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1405</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1420</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>98</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1404</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1418</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Understanding Equity</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1406</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>110</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1408</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1411</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1416</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1413</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1415</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1409</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1414</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1417</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1412</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1410</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>194</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380351.410896</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378717.688104</real>
+ </dict>
+ <string>{1740, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379929.95300499</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377885.19557899</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1427</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1442</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1439</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1441</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1425</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1440</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>406</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1424</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1438</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Dealing with Petty Cash</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1426</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>111</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1428</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1431</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1436</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1433</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1435</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1429</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1434</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1437</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1432</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1430</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>195</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380353.394696</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378719.23175099</real>
+ </dict>
+ <string>{917, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379931.94546899</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377888.459512</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1447</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1462</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1459</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1461</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1445</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1460</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1463</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1444</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1458</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Working with multiple funds and accounts</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1446</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>112</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1448</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1451</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1456</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1453</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1455</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1449</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1454</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1457</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1452</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1450</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>196</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380355.220451</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378720.87155801</real>
+ </dict>
+ <string>{4642, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379933.49533001</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377891.11512199</real>
+ </dict>
+ <string>{49, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1468</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1483</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1480</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1482</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1466</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1481</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>448</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1465</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1479</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Archiving previous years</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1467</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>113</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1469</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1472</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1477</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1474</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1476</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1470</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1475</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1478</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1473</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1471</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>197</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380357.931027</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378722.51128501</real>
+ </dict>
+ <string>{2384, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379935.17104501</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377893.81884101</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1488</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1503</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1500</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1502</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1486</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1501</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>364</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1485</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1499</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Virtual postings</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1487</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>114</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1489</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1492</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1497</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1494</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1496</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1490</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1495</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1498</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1493</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1491</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>198</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380359.62675899</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378724.13517299</real>
+ </dict>
+ <string>{1493, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379936.75089499</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377896.94637701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1508</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1523</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1520</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1522</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1506</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1521</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>474</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1505</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1519</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Automated postings</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1507</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>115</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1509</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1512</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1517</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1514</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1516</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1510</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1515</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1518</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1513</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1511</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>199</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380361.357301</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378725.78299999</real>
+ </dict>
+ <string>{2854, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379938.15314099</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377900.69808099</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1528</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1543</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1540</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1542</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1526</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1541</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1544</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1525</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1539</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Using Emacs to Keep Your Ledger</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1527</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>116</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1529</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1532</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1537</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1534</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1536</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1530</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1535</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1538</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1533</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1531</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>200</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380363.056099</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378727.49465901</real>
+ </dict>
+ <string>{2858, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379940.06478399</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377905.15337399</real>
+ </dict>
+ <string>{40, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1549</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1564</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1561</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1563</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1547</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1562</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1187</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1546</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1560</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Using GnuCash to Keep Your Ledger</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1548</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>117</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1550</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1553</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1558</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1555</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1557</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1551</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1556</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1559</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1554</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1552</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>201</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380364.75349799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378729.09454301</real>
+ </dict>
+ <string>{639, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379941.73997501</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377908.73699099</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1569</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1584</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1581</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1583</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1567</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1582</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1585</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1566</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1580</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Using timeclock to record billable time</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1568</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>118</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1570</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1573</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1578</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1575</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1577</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1571</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1576</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1579</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1574</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1572</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>202</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380366.76199099</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378730.59814101</real>
+ </dict>
+ <string>{2566, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379943.24100199</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377911.840628</real>
+ </dict>
+ <string>{48, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1590</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1605</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1602</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1604</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1588</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1603</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>221</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1587</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1601</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Using XML</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1589</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>119</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1591</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1594</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1599</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1596</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1598</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1592</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1597</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1600</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1595</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1593</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>203</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380369.75532499</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378732.094033</real>
+ </dict>
+ <string>{4369, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379944.92043799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377914.904223</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379850.95137599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377347.08223999</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1615</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1630</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1627</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1629</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1613</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1628</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1631</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1612</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1626</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Random things</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1614</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>19</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1616</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1619</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1624</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1621</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1623</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1617</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1622</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1625</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1620</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1618</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>204</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380371.35135299</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378734.317837</real>
+ </dict>
+ <string>{1117, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379854.263753</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377347.24779701</real>
+ </dict>
+ <string>{22, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1636</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1651</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1648</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1650</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1634</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1649</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1061</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1633</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1647</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Anatomy of a journal file</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1635</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1637</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1640</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1645</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1642</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1644</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1638</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1643</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1646</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1641</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1639</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>205</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380151.76080799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378736.09351999</real>
+ </dict>
+ <string>{1310, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379856.11152199</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377347.429481</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1656</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1661</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1658</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1660</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1654</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1659</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>733</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1653</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1657</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Example accounting practices</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1655</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>21</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379857.886282</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377347.60771599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1666</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1681</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1678</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1680</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1664</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1679</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1061</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1663</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1677</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Generating useful reports</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1665</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>22</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1667</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1670</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1675</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1672</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1674</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1668</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1673</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1676</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1671</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1669</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>207</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380149.71518299</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378739.56495801</real>
+ </dict>
+ <string>{754, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379859.73246899</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377347.77389699</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1685</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1690</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1687</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1689</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1683</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1688</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>71</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>497</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1686</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1684</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>23</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379861.583101</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377347.94751</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1694</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1699</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1696</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1698</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1692</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1697</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>495</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>476</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1695</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1693</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>24</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379863.35776001</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377348.06632301</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1704</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1751</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1748</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1750</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1702</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1749</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>77</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1701</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1747</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Scripting in Python</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1703</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>25</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1705</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1716</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1708</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1714</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1711</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1713</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1706</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1712</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1715</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1710</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1709</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1707</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>219</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <integer>2</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380799.16811699</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380547.075324</real>
+ </dict>
+ <string>{553, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1720</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1746</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1743</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1745</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1718</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1744</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>474</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1717</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1742</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Creating a session</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1719</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>220</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1721</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1731</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1724</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1729</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1726</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1728</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1722</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1727</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1730</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1710</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1725</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1723</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>221</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267382480.38211599</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380784.236047</real>
+ </dict>
+ <string>{898, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1735</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1740</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1737</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1739</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1733</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1738</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1741</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1710</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1732</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1736</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Initialize a session</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1734</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>222</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>278219176.55654401</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380893.915546</real>
+ </dict>
+ <string>{284, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380833.86209199</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380770.90190899</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380555.01635501</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377348.24222499</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1756</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1850</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1847</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1849</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1754</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1848</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>98</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1753</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1846</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>The design of Ledger</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1755</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>26</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1757</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1767</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1797</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1816</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1826</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1836</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1760</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1765</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1762</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1764</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1758</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1763</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1766</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1761</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1759</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>211</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380116.415748</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378750.25930101</real>
+ </dict>
+ <string>{1193, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1771</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1796</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1793</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1795</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1769</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1794</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>200</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1768</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1792</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Numerics</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1770</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>120</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1772</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1776</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1791</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1788</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1790</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1774</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1789</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>364</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1773</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1787</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Basic amounts</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1775</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>121</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1777</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1780</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1785</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1782</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1784</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1778</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1783</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1786</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1781</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1779</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>213</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380118.14631701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378761.45012</real>
+ </dict>
+ <string>{390, 0}</string>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380074.89227101</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377926.46286899</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379949.70617801</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377921.40766799</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1801</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1815</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1812</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1814</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1799</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1813</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>427</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1798</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1811</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Journal Representation</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1800</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>122</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1802</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1805</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1810</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1807</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1809</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1803</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1808</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1187</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1806</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1804</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>214</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380119.71273199</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267378763.66567799</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379951.51897901</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377933.94970801</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1820</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1825</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1822</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1824</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1818</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1823</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>221</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1817</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1821</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Reporting</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1819</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>123</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379953.14888</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377937.316921</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1830</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1835</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1832</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1834</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1828</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1833</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>474</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1827</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1831</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Terminal Interface</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1829</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>124</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379954.585186</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377941.48499</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1840</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1845</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1842</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1844</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1838</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1843</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>662</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1837</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1841</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>General Utility</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1839</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>125</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379958.53720701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377943.89263299</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379867.22076699</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267377348.410979</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1855</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1860</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1857</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1859</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1853</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1858</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1861</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1852</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1856</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>End Matter</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1854</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>218</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379869.017694</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267379592.95455101</real>
+ </dict>
+ <string>{4, 0}</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267376867.711595</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267376867.71159199</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1869</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1873</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1870</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1872</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1868</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1871</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1867</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Research</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267376867.71165699</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267376867.71165499</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1877</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1881</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1878</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1880</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1876</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1879</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1875</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1710</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Trash</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1710</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267376867.71169701</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267376867.71169499</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1886</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1901</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1898</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1900</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1884</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1899</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1883</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1897</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Notes</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1885</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>224</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1887</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>children</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1891</integer>
+ </dict>
+ <key>createdDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1896</integer>
+ </dict>
+ <key>includeInExport</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>isLeaf</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <key>keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1893</integer>
+ </dict>
+ <key>label</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>modifiedDate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1895</integer>
+ </dict>
+ <key>pageBreakBefore</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>preservesFormatting</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>properties</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1889</integer>
+ </dict>
+ <key>references</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1894</integer>
+ </dict>
+ <key>selectedRangeString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ <key>status</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>synopsisString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>tags</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>targetCount</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>targetCountType</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <key>title</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1888</integer>
+ </dict>
+ <key>type</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1892</integer>
+ </dict>
+ <key>wordCountTarget</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <string>Note (Content), 22 Jun 2009, 17:51</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1890</integer>
+ </dict>
+ </array>
+ </dict>
+ <integer>225</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <integer>20</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267382313.75795001</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267382313.75794899</real>
+ </dict>
+ <integer>15</integer>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267382313.729581</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267382313.72957999</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1928</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1903</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1910</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1913</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1916</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1919</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1922</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1925</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1905</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1906</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1907</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1909</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Tag</string>
+ <string>LabelColor</string>
+ <string>LabelString</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1908</integer>
+ </dict>
+ <key>NSColorSpace</key>
+ <integer>3</integer>
+ <key>NSWhite</key>
+ <data>
+ MQA=
+ </data>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSColor</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSColor</string>
+ </dict>
+ <string>No Label</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1905</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1906</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1911</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1912</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1908</integer>
+ </dict>
+ <key>NSColorSpace</key>
+ <integer>1</integer>
+ <key>NSRGB</key>
+ <data>
+ MC44OTk5OTk5NzYyIDAuOTIwMDAwMDE2NyAwLjk0OTk5OTk4ODEA
+ </data>
+ </dict>
+ <string>Concept</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1905</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1906</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1710</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1914</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1915</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1908</integer>
+ </dict>
+ <key>NSColorSpace</key>
+ <integer>1</integer>
+ <key>NSRGB</key>
+ <data>
+ MC45ODUwMDAwMTQzIDAuODc1IDAuODUwMDAwMDIzOAA=
+ </data>
+ </dict>
+ <string>Chapter</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1905</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1906</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1917</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1918</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1908</integer>
+ </dict>
+ <key>NSColorSpace</key>
+ <integer>1</integer>
+ <key>NSRGB</key>
+ <data>
+ MC43ODMwOTkyMzQxIDAuMzk0MzgyOTIzOCAwLjg0MDE4NzcyODQA
+ </data>
+ </dict>
+ <string>MS Page</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1905</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1906</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1920</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1921</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1908</integer>
+ </dict>
+ <key>NSColorSpace</key>
+ <integer>1</integer>
+ <key>NSRGB</key>
+ <data>
+ MC4xOTc1NTEzNjk3IDAuOTExNjQ3Mzc5NCAwLjc5ODQ0MDAzOTIA
+ </data>
+ </dict>
+ <string>Example</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1905</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1906</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1923</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1924</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1908</integer>
+ </dict>
+ <key>NSColorSpace</key>
+ <integer>1</integer>
+ <key>NSRGB</key>
+ <data>
+ MC4yNzc3NzQ3MjE0IDAuNzY4MjI5NjAzOCAwLjMzNTIyMjc1MDkA
+ </data>
+ </dict>
+ <string>Table</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1905</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1906</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>39</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1926</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1927</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1908</integer>
+ </dict>
+ <key>NSColorSpace</key>
+ <integer>1</integer>
+ <key>NSRGB</key>
+ <data>
+ MC42Mjg4NzA5MDQ0IDAuNDc3Mzk3MDU0NCAwLjU1Mzk2OTk3OTMA
+ </data>
+ </dict>
+ <string>List</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <string>Label</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1928</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1931</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1934</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1936</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1938</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1940</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1942</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1932</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1933</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>StatusName</string>
+ <string>N/A</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1932</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1935</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>To Do</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1932</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1710</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1937</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>First Draft</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1932</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1939</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Revised Draft</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1932</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1941</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Final Draft</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1904</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1932</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1943</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Done</string>
+ <string>Status</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1951</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1946</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1947</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1948</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1949</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1950</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1946</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1947</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1948</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1949</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1950</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Green</string>
+ <string>Yellow</string>
+ <string>Pink</string>
+ <string>Orange</string>
+ <string>Blue</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array/>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1951</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1956</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1957</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1958</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1959</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1971</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1971</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>MetaData</string>
+ <string>ParseAnnotations</string>
+ <string>ParseFootnotes</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1928</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1960</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1965</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1968</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1961</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1962</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1963</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1964</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>key</string>
+ <string>data</string>
+ <string>Title</string>
+ <string>Ledger</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1961</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1962</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1966</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1967</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Author</string>
+ <string>Anonymous</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1961</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1962</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1969</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1970</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Base Header Level</string>
+ <string>1</string>
+ <true/>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>AutoCompleteList</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1954</integer>
+ </dict>
+ <key>BinderContents</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ <key>DefaultLabelTag</key>
+ <integer>0</integer>
+ <key>DefaultStatusTag</key>
+ <integer>0</integer>
+ <key>HighlightNames</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1945</integer>
+ </dict>
+ <key>Keywords</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1952</integer>
+ </dict>
+ <key>LabelList</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1902</integer>
+ </dict>
+ <key>LabelTitle</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1929</integer>
+ </dict>
+ <key>MultiMarkdownSettings</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1955</integer>
+ </dict>
+ <key>ProjectReferences</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1953</integer>
+ </dict>
+ <key>StatusList</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1930</integer>
+ </dict>
+ <key>StatusTitle</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1944</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/info.plist b/doc/Ledger.scriv/info.plist
new file mode 100644
index 00000000..535aabb7
--- /dev/null
+++ b/doc/Ledger.scriv/info.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>SCRProjectVersion</key>
+ <integer>4</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/100.snapshots b/doc/Ledger.scriv/snapshots/100.snapshots
new file mode 100644
index 00000000..ebe5d6f8
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/100.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Reporting monthly expenses</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.21601799</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/101.snapshots b/doc/Ledger.scriv/snapshots/101.snapshots
new file mode 100644
index 00000000..eea13921
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/101.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Visualizing with Gnuplot</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.22663701</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/102.snapshots b/doc/Ledger.scriv/snapshots/102.snapshots
new file mode 100644
index 00000000..7cf0a3e3
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/102.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsubsection Typical plots</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.236155</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/103.snapshots b/doc/Ledger.scriv/snapshots/103.snapshots
new file mode 100644
index 00000000..d6cbe252
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/103.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Budgeting and forecasting</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.246214</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/104.snapshots b/doc/Ledger.scriv/snapshots/104.snapshots
new file mode 100644
index 00000000..cf3db51a
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/104.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Budgeting</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.25083199</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/105.snapshots b/doc/Ledger.scriv/snapshots/105.snapshots
new file mode 100644
index 00000000..61efcdd3
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/105.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Forecasting</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.26045999</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/106.snapshots b/doc/Ledger.scriv/snapshots/106.snapshots
new file mode 100644
index 00000000..52353462
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/106.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Commodities and Currencies</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.27013901</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/107.snapshots b/doc/Ledger.scriv/snapshots/107.snapshots
new file mode 100644
index 00000000..5f102b83
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/107.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Commodity price histories</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.27969399</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/108.snapshots b/doc/Ledger.scriv/snapshots/108.snapshots
new file mode 100644
index 00000000..eea1ca01
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/108.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Commodity equivalencies</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.28911799</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/109.snapshots b/doc/Ledger.scriv/snapshots/109.snapshots
new file mode 100644
index 00000000..a566ac65
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/109.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Accounts and Inventories</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.298612</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/110.snapshots b/doc/Ledger.scriv/snapshots/110.snapshots
new file mode 100644
index 00000000..3800869b
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/110.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Understanding Equity</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.308036</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/111.snapshots b/doc/Ledger.scriv/snapshots/111.snapshots
new file mode 100644
index 00000000..446030b7
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/111.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Dealing with Petty Cash</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.317444</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/112.snapshots b/doc/Ledger.scriv/snapshots/112.snapshots
new file mode 100644
index 00000000..fb917bc6
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/112.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Working with multiple funds and accounts</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.326754</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/113.snapshots b/doc/Ledger.scriv/snapshots/113.snapshots
new file mode 100644
index 00000000..8e5879d2
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/113.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Archiving previous years</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.336301</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/114.snapshots b/doc/Ledger.scriv/snapshots/114.snapshots
new file mode 100644
index 00000000..017104e1
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/114.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Virtual postings</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.34586301</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/115.snapshots b/doc/Ledger.scriv/snapshots/115.snapshots
new file mode 100644
index 00000000..a1362076
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/115.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Automated postings</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.35530999</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/116.snapshots b/doc/Ledger.scriv/snapshots/116.snapshots
new file mode 100644
index 00000000..92d8431d
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/116.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Using Emacs to Keep Your Ledger</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.36469099</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/117.snapshots b/doc/Ledger.scriv/snapshots/117.snapshots
new file mode 100644
index 00000000..cc401f22
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/117.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Using GnuCash to Keep Your Ledger</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.37472501</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/118.snapshots b/doc/Ledger.scriv/snapshots/118.snapshots
new file mode 100644
index 00000000..70000484
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/118.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Using timeclock to record billable time</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.384195</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/119.snapshots b/doc/Ledger.scriv/snapshots/119.snapshots
new file mode 100644
index 00000000..181ae0fc
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/119.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Using XML</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.39373201</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/12.snapshots b/doc/Ledger.scriv/snapshots/12.snapshots
new file mode 100644
index 00000000..1b6aa0d3
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/12.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Building the program</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.68231499</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/120.snapshots b/doc/Ledger.scriv/snapshots/120.snapshots
new file mode 100644
index 00000000..d9f0eec8
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/120.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Numerics</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.46126601</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/121.snapshots b/doc/Ledger.scriv/snapshots/121.snapshots
new file mode 100644
index 00000000..48988008
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/121.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Basic amounts</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.46583501</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/122.snapshots b/doc/Ledger.scriv/snapshots/122.snapshots
new file mode 100644
index 00000000..cec4e5b9
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/122.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Journal Representation</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.47530201</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/123.snapshots b/doc/Ledger.scriv/snapshots/123.snapshots
new file mode 100644
index 00000000..bd0a4a22
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/123.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Reporting</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.485093</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/124.snapshots b/doc/Ledger.scriv/snapshots/124.snapshots
new file mode 100644
index 00000000..8134ae6d
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/124.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Terminal Interface</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.48985201</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/125.snapshots b/doc/Ledger.scriv/snapshots/125.snapshots
new file mode 100644
index 00000000..b0f1642f
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/125.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section General Utility</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.494477</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/126.snapshots b/doc/Ledger.scriv/snapshots/126.snapshots
new file mode 100644
index 00000000..afb2c9b0
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/126.snapshots
@@ -0,0 +1,466 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>This chapter describes ledger's features and serves as a quick
+reference. You may wish to survey this to get an overview before diving
+in to the @ref{Ledger Tutorial} and more detailed examples that follow.
+
+Ledger has a very simple command-line interface, named---enticing
+enough---@command{ledger}. It supports a few reporting commands, and
+a large number of options for refining the output from those commands.
+The basic syntax of any ledger command is:
+
+@example
+ledger [OPTIONS...] COMMAND [ARGS...]
+@end example
+
+Command options must always precede the command word. After the
+command word there may appear any number of arguments. For most
+commands, these arguments are regular expressions that cause the
+output to relate only to postings matching those regular
+expressions. For the @command{transaction} command, the arguments have a
+special meaning, described below.
+
+The regular expressions arguments always match the account name that a
+posting refers to. To match on the payee of the transaction instead,
+precede the regular expression with @samp{--}. For example, the
+following balance command reports account totals for rent, food and
+movies, but only those whose payee matches Freddie:
+
+@example
+ledger bal rent food movies -- freddie
+@end example
+
+There are many, many command options available with the
+@command{ledger} command, and it takes a while to master them.
+However, none of them are required to use the basic reporting
+commands.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.70523399</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/128.snapshots b/doc/Ledger.scriv/snapshots/128.snapshots
new file mode 100644
index 00000000..d72da803
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/128.snapshots
@@ -0,0 +1,438 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The @command{balance} command reports the current balance of all
+accounts. It accepts a list of optional regexps, which confine the
+balance report to the matching accounts. If an account contains
+multiple types of commodities, each commodity's total is reported
+separately.
+</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.71900299</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/129.snapshots b/doc/Ledger.scriv/snapshots/129.snapshots
new file mode 100644
index 00000000..203e8f0f
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/129.snapshots
@@ -0,0 +1,449 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The @command{register} command displays all the postings occurring
+in a single account, line by line. The account regexp must be
+specified as the only argument to this command. If any regexps occur
+after the required account name, the register will contain only those
+postings that match. Very useful for hunting down a particular
+posting.
+
+The output from @command{register} is very close to what a typical
+checkbook, or single-account ledger, would look like. It also shows a
+running balance. The final running balance of any register should
+always be the same as the current balance of that account.
+
+If you have Gnuplot installed, you may plot the amount or running
+total of any register by using the script @file{report}, which is
+included in the Ledger distribution. The only requirement is that you
+add either @option{-j} or @option{-J} to your register command, in
+order to plot either the amount or total column, respectively.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.72875401</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/13.snapshots b/doc/Ledger.scriv/snapshots/13.snapshots
new file mode 100644
index 00000000..f54072d2
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/13.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Getting help</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.69155401</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/130.snapshots b/doc/Ledger.scriv/snapshots/130.snapshots
new file mode 100644
index 00000000..11acbd0a
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/130.snapshots
@@ -0,0 +1,440 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The @command{print} command prints out ledger transactions in a textual
+format that can be parsed by Ledger. They will be properly formatted,
+and output in the most economic form possible. The ``print'' command
+also takes a list of optional regexps, which will cause only those
+postings which match in some way to be printed.
+
+The @command{print} command can be a handy way to clean up a ledger
+file whose formatting has gotten out of hand.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.737997</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/131.snapshots b/doc/Ledger.scriv/snapshots/131.snapshots
new file mode 100644
index 00000000..d0cfb474
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/131.snapshots
@@ -0,0 +1,444 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The @command{output} command is very similar to the @command{print}
+command, except that it attempts to replicate the specified ledger
+file epostly. The format of the command is:
+
+@example
+ledger -f FILENAME output FILENAME
+@end example
+
+Where @file{FILENAME} is the name of the ledger file to output. The
+reason for specifying this command is that only transactions contained
+within that file will be output, and not an included transactions (as can
+happen with the @command{print} command).</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.74727699</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/132.snapshots b/doc/Ledger.scriv/snapshots/132.snapshots
new file mode 100644
index 00000000..548d27b7
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/132.snapshots
@@ -0,0 +1,437 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The @command{xml} command outputs results similar to what
+@command{print} and @command{register} display, but as an XML form.
+This data can then be read in and processed. Use the
+@option{--totals} option to include the running total with each
+posting.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.75649899</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/133.snapshots b/doc/Ledger.scriv/snapshots/133.snapshots
new file mode 100644
index 00000000..87666c85
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/133.snapshots
@@ -0,0 +1,440 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The @command{emacs} command outputs results in a form that can be read
+directly by Emacs Lisp. The format of the sexp is:
+
+@example
+((BEG-POS CLEARED DATE CODE PAYEE
+ (ACCOUNT AMOUNT)...) ; list of postings
+ ...) ; list of transactions
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.765847</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/134.snapshots b/doc/Ledger.scriv/snapshots/134.snapshots
new file mode 100644
index 00000000..40a7e0d0
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/134.snapshots
@@ -0,0 +1,435 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The @command{equity} command prints out accounts balances as if they
+were transactions. This makes it easy to establish the starting balances
+for an account, such as when @ref{Archiving previous years}.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.775161</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/135.snapshots b/doc/Ledger.scriv/snapshots/135.snapshots
new file mode 100644
index 00000000..637c195b
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/135.snapshots
@@ -0,0 +1,440 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The @command{prices} command displays the price history for matching
+commodities. The @option{-A} flag is useful with this report, to
+display the running average price, or @option{-D} to show each price's
+deviation from that average.
+
+There is also a @command{pricesdb} command which outputs the same
+information as @command{prices}, but does in a format that can be
+parsed by Ledger.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.784486</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/136.snapshots b/doc/Ledger.scriv/snapshots/136.snapshots
new file mode 100644
index 00000000..9da10182
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/136.snapshots
@@ -0,0 +1,484 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The @command{xact} commands simplifies the creation of new transactions.
+It works on the principle that 80% of all postings are variants of
+earlier postings. Here's how it works:
+
+Say you currently have this posting in your ledger file:
+
+@smallexample
+2004/03/15 * Viva Italiano
+ Expenses:Food $12.45
+ Expenses:Tips $2.55
+ Liabilities:MasterCard $-15.00
+@end smallexample
+
+Now it's @samp{2004/4/9}, and you've just eating at @samp{Viva
+Italiano} again. The epost amounts are different, but the overall
+form is the same. With the @command{xact} command you can type:
+
+@example
+ledger xact 2004/4/9 viva food 11 tips 2.50
+@end example
+
+This produces the following output:
+
+@smallexample
+2004/04/09 Viva Italiano
+ Expenses:Food $11.00
+ Expenses:Tips $2.50
+ Liabilities:MasterCard $-13.50
+@end smallexample
+
+It works by finding a past posting matching the regular expression
+@samp{viva}, and assuming that any accounts or amounts specified will
+be similar to that earlier posting. If Ledger does not succeed in
+generating a new transaction, an error is printed and the exit code is set
+to @samp{1}.
+
+There is a shell script in the distribution's @file{scripts} directory
+called @file{xact}, which simplifies the task of adding a new transaction
+to your ledger. It launches @command{vi} to confirm that the transaction
+looks appropriate.
+
+Here are a few more examples of the @command{xact} command, assuming
+the above journal transaction:
+
+@example
+ledger xact 4/9 viva 11.50
+ledger xact 4/9 viva 11.50 checking # (from `checking')
+ledger xact 4/9 viva food 11.50 tips 8
+ledger xact 4/9 viva food 11.50 tips 8 cash
+ledger xact 4/9 viva food $11.50 tips $8 cash
+ledger xact 4/9 viva dining "DM 11.50"
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.79372501</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/137.snapshots b/doc/Ledger.scriv/snapshots/137.snapshots
new file mode 100644
index 00000000..eaa2456d
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/137.snapshots
@@ -0,0 +1,446 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>With all of the reports, command-line options are useful to modify the
+output generated. These command-line options always occur before the
+command word. This is done to distinguish options from exclusive
+regular expressions, which also begin with a dash. The basic form for
+most commands is:
+
+@example
+ledger [OPTIONS] COMMAND [REGEXPS...] [-- [REGEXPS...]]
+@end example
+
+The @var{OPTIONS} and @var{REGEXPS} expressions are both optional.
+You could just use @samp{ledger balance}, without any options---which
+prints a summary of all accounts. But for more specific reporting, or
+to change the appearance of the output, options are needed.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.80274901</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/138.snapshots b/doc/Ledger.scriv/snapshots/138.snapshots
new file mode 100644
index 00000000..bb9cb38e
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/138.snapshots
@@ -0,0 +1,480 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>These are the most basic command options. Most likely, the user will
+want to set them using environment variables (see @ref{Options}),
+instead of using actual command-line options:
+
+@option{--help} (@option{-h}) prints a summary of all the options, and
+what they are used for. This can be a handy way to remember which
+options do what. This help screen is also printed if ledger is run
+without a command.
+
+@option{--version} (@option{-v}) prints the current version of ledger
+and exits. This is useful for sending bug reports, to let the author
+know which version of ledger you are using.
+
+@option{--file FILE} (@option{-f FILE}) reads FILE as a ledger file.
+This command may be used multiple times. FILE may also be a list of
+file names separated by colons. Typically, the environment variable
+@env{LEDGER_FILE} is set, rather than using this command-line option.
+
+@option{--output FILE} (@option{-o FILE}) redirects output from any
+command to @var{FILE}. By default, all output goes to standard
+output.
+
+@option{--init-file FILE} (@option{-i FILE}) causes FILE to be read by
+ledger before any other ledger file. This file may not contain any
+postings, but it may contain option settings. To specify options
+in the init file, use the same syntax as the command-line. Here's an
+example init file:
+
+@smallexample
+--price-db ~/finance/.pricedb
+
+; ~/.ledgerrc ends here
+@end smallexample
+
+Option settings on the command-line or in the environment always take
+precedence over settings in the init file.
+
+@option{--cache FILE} identifies FILE as the default binary cache
+file. That is, if the ledger files to be read are specified using the
+environment variable @env{LEDGER_FILE}, then whenever a command is
+finished a binary copy will be written to the specified cache, to
+speed up the loading time of subsequent queries. This filename can
+also be given using the environment variable @env{LEDGER_CACHE}, or by
+putting the option into your init file. The @option{--no-cache}
+option causes Ledger to always ignore the binary cache.
+
+@option{--account NAME} (@option{-a NAME}) specifies the default
+account which QIF file postings are assumed to relate to.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.812042</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/139.snapshots b/doc/Ledger.scriv/snapshots/139.snapshots
new file mode 100644
index 00000000..83995e33
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/139.snapshots
@@ -0,0 +1,529 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>These options change which postings affect the outcome of a
+report, in ways other than just using regular expressions:
+
+@option{--current}(@option{-c}) displays only transactions occurring on or
+before the current date.
+
+@option{--begin DATE} (@option{-b DATE}) constrains the report to
+transactions on or after @var{DATE}. Only transactions after that date will be
+calculated, which means that the running total in the balance report
+will always start at zero with the first matching transaction. (Note: This
+is different from using @option{--display} to constrain what is
+displayed).
+
+@option{--end DATE} (@option{-e DATE}) constrains the report so that
+transactions on or after @var{DATE} are not considered. The ending date
+is inclusive.
+
+@option{--period STR} (@option{-p STR}) sets the reporting period
+to @var{STR}. This will subtotal all matching transactions within each
+period separately, making it easy to see weekly, monthly, quarterly,
+etc., posting totals. A period string can even specify the
+beginning and end of the report range, using simple terms like ``last
+june'' or ``next month''. For more using period expressions, see
+@ref{Period expressions}.
+
+@option{--period-sort EXPR} sorts the postings within each
+reporting period using the value expression @var{EXPR}. This is most
+often useful when reporting monthly expenses, in order to view the
+highest expense categories at the top of each month:
+
+@example
+ledger -M --period-sort -At reg ^Expenses
+@end example
+
+@option{--cleared} (@option{-C}) displays only postings whose transaction
+has been marked ``cleared'' (by placing an asterix to the right of the
+date).
+
+@option{--uncleared} (@option{-U}) displays only postings whose
+transaction has not been marked ``cleared'' (i.e., if there is no asterix to
+the right of the date).
+
+@option{--real} (@option{-R}) displays only real postings, not
+virtual. (A virtual posting is indicated by surrounding the
+account name with parentheses or brackets; see the section on using
+virtual postings for more information).
+
+@option{--actual} (@option{-L}) displays only actual postings, and
+not those created due to automated postings.
+
+@option{--related} (@option{-r}) displays postings that are
+related to whichever postings would otherwise have matched the
+filtering criteria. In the register report, this shows where money
+went to, or the account it came from. In the balance report, it shows
+all the accounts affected by transactions having a related posting.
+For example, if a file had this transaction:
+
+@smallexample
+2004/03/20 Safeway
+ Expenses:Food $65.00
+ Expenses:Cash $20.00
+ Assets:Checking $-85.00
+@end smallexample
+
+And the register command was:
+
+@example
+ledger -r register food
+@end example
+
+The following would be output, showing the postings related to the
+posting that matched:
+
+@smallexample
+2004/03/20 Safeway Expenses:Cash $-20.00 $-20.00
+ Assets:Checking $85.00 $65.00
+@end smallexample
+
+@option{--budget} is useful for displaying how close your postings
+meet your budget. @option{--add-budget} also shows unbudgeted
+postings, while @option{--unbudgeted} shows only those.
+@option{--forecast} is a related option that projects your budget into
+the future, showing how it will affect future balances.
+@xref{Budgeting and forecasting}.
+
+@option{--limit EXPR} (@option{-l EXPR}) limits which postings
+take part in the calculations of a report.
+
+@option{--amount EXPR} (@option{-t EXPR}) changes the value expression
+used to calculate the ``value'' column in the @command{register}
+report, the amount used to calculate account totals in the
+@command{balance} report, and the values printed in the
+@command{equity} report. @xref{Value expressions}.
+
+@option{--total EXPR} (@option{-T EXPR}) sets the value expression
+used for the ``totals'' column in the @command{register} and
+@command{balance} reports.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.821309</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/14.snapshots b/doc/Ledger.scriv/snapshots/14.snapshots
new file mode 100644
index 00000000..63443d72
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/14.snapshots
@@ -0,0 +1,443 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Ledger is written in ANSI C++, and should compile on any platform. It
+depends on the GNU multiprecision integer library (libgmp), and the
+Perl regular expression library (libpcre). It was developed using GNU
+make and gcc 3.3, on a PowerBook running OS/X.
+
+To build and install once you have these libraries on your system,
+enter these commands:
+
+@example
+./configure &amp;&amp; make install
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.686896</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/140.snapshots b/doc/Ledger.scriv/snapshots/140.snapshots
new file mode 100644
index 00000000..815ce0b4
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/140.snapshots
@@ -0,0 +1,554 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>These options affect only the output, but not which postings are
+used to create it:
+
+@option{--collapse} (@option{-n}) causes transactions in a
+@command{register} report with multiple postings to be collapsed
+into a single, subtotaled transaction.
+
+@option{--subtotal} (@option{-s}) causes all transactions in a
+@command{register} report to be collapsed into a single, subtotaled
+transaction.
+
+@option{--by-payee} (@option{-P}) reports subtotals by payee.
+
+@option{--comm-as-payee} (@option{-x}) changes the payee of every
+posting to be the commodity used in that posting. This can be
+useful when combined with other options, such as @option{-s}.
+
+@option{--empty} (@option{-E}) includes even empty accounts in the
+@command{balance} report.
+
+@option{--weekly} (@option{-W}) reports posting totals by the
+week. The week begins on whichever day of the week begins the month
+containing that posting. To set a specific begin date, use a
+period string, such as @samp{weekly from DATE}. @option{--monthly}
+(@option{-M}) reports posting totals by month; @option{--yearly}
+(@option{-Y}) reports posting totals by year. For more complex
+period, using the @option{--period} option described above.
+
+@option{--dow} reports postings totals for each day of the week.
+This is an easy way to see if weekend spending is more than on
+weekdays.
+
+@option{--sort EXPR} (@option{-S EXPR}) sorts a report by comparing
+the values determined using the value expression @var{EXPR}. For
+example, using @option{-S -UT} in the balance report will sort account
+balances from greatest to least, using the absolute value of the
+total. For more on how to use value expressions, see @ref{Value
+expressions}.
+
+@option{--wide} (@option{-w}) causes the default @command{register}
+report to assume 132 columns instead of 80.
+
+@option{--head} causes only the first N transactions to be printed. This
+is different from using the command-line utility @command{head}, which
+would limit to the first N postings. @option{--tail} outputs only
+the last N transactions. Both options may be used simultaneously. If a
+negative amount is given, it will invert the meaning of the flag
+(instead of the first five transactions being printed, for example, it
+would print all but the first five).
+
+@option{--pager} tells Ledger to pass its output to the given pager
+program---very useful when the output is especially long. This
+behavior can be made the default by setting the @env{LEDGER_PAGER}
+environment variable.
+
+@option{--average} (@option{-A}) reports the average posting
+value.
+
+@option{--deviation} (@option{-D}) reports each posting's
+deviation from the average. It is only meaningful in the
+@command{register} and @command{prices} reports.
+
+@option{--percentage} (@option{-%}) shows account subtotals in the
+@command{balance} report as percentages of the parent account.
+
+@option{--totals} include running total information in the
+@command{xml} report.
+
+@option{--amount-data} (@option{-j}) changes the @command{register}
+report so that it output nothing but the date and the value column,
+and the latter without commodities. This is only meaningful if the
+report uses a single commodity. This data can then be fed to other
+programs, which could plot the date, analyze it, etc.
+
+@option{--total-data} (@option{-J}) changes the @command{register}
+report so that it output nothing but the date and totals column,
+without commodities.
+
+@option{--display EXPR} (@option{-d EXPR}) limits which postings
+or accounts or actually displayed in a report. They might still be
+calculated, and be part of the running total of a register report, for
+example, but they will not be displayed. This is useful for seeing
+last month's checking postings, against a running balance which
+includes all posting values:
+
+@example
+ledger -d "d&gt;=[last month]" reg checking
+@end example
+
+The output from this command is very different from the following,
+whose running total includes only postings from the last month
+onward:
+
+@example
+ledger -p "last month" reg checking
+@end example
+
+Which is more useful depends on what you're looking to know: the total
+amount for the reporting range (@option{-p}), or simply a display
+restricted to the reporting range (using @option{-d}).
+
+@option{--date-format STR} (@option{-y STR}) changes the basic date
+format used by reports. The default uses a date like 2004/08/01,
+which represents the default date format of @samp{%Y/%m/%d}. To
+change the way dates are printed in general, the easiest way is to put
+@option{--date-format FORMAT} in the Ledger initialization file
+@file{~/.ledgerrc} (or the file referred to by @env{LEDGER_INIT}).
+
+@option{--format STR} (@option{-F STR}) sets the reporting format for
+whatever report ledger is about to make. @xref{Format strings}.
+There are also specific format commands for each report type:
+
+@itemize
+@item @option{--balance-format STR}
+@item @option{--register-format STR}
+@item @option{--print-format STR}
+@item @option{--plot-amount-format STR} (-j @command{register})
+@item @option{--plot-total-format STR} (-J @command{register})
+@item @option{--equity-format STR}
+@item @option{--prices-format STR}
+@item @option{--wide-register-format STR} (-w @command{register})
+@end itemize</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.830576</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/141.snapshots b/doc/Ledger.scriv/snapshots/141.snapshots
new file mode 100644
index 00000000..6b28fd86
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/141.snapshots
@@ -0,0 +1,481 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>These options affect how commodity values are displayed:
+
+@option{--price-db FILE} sets the file that is used for recording
+downloaded commodity prices. It is always read on startup, to
+determine historical prices. Other settings can be placed in this
+file manually, to prevent downloading quotes for a specific, for
+example. This is done by adding a line like the following:
+
+@example
+; Don't download quotes for the dollar, or timelog values
+N $
+N h
+@end example
+
+@option{--price-exp MINS} (@option{-L MINS}) sets the expected
+freshness of price quotes, in minutes. That is, if the last known
+quote for any commodity is older than this value---and if
+@option{--download} is being used---then the Internet will be
+consulted again for a newer price. Otherwise, the old price is still
+considered to be fresh enough.
+
+@option{--download} (@option{-Q}) causes quotes to be automagically
+downloaded, as needed, by running a script named @command{getquote}
+and expecting that script to return a value understood by ledger. A
+sample implementation of a @command{getquote} script, implemented in
+Perl, is provided in the distribution. Downloaded quote price are
+then appended to the price database, usually specified using the
+environment variable @env{LEDGER_PRICE_DB}.
+
+There are several different ways that ledger can report the totals it
+displays. The most flexible way to adjust them is by using value
+expressions, and the @option{-t} and @option{-T} options. However,
+there are also several ``default'' reports, which will satisfy most
+users basic reporting needs:
+
+@table @code
+@item -O, --quantity
+Reports commodity totals (this is the default)
+
+@item -B, --basis
+Reports the cost basis for all postings.
+
+@item -V, --market
+Reports the last known market value for all commodities.
+
+@item -G --gain
+Reports the net gain/loss for all commodities in the report that have
+a price history.
+@end table</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.84002501</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/142.snapshots b/doc/Ledger.scriv/snapshots/142.snapshots
new file mode 100644
index 00000000..0c86052e
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/142.snapshots
@@ -0,0 +1,445 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Every option to ledger may be set using an environment variable. If
+an option has a long name such @option{--this-option}, setting the
+environment variable @env{LEDGER_THIS_OPTION} will have the same
+affect as specifying that option on the command-line. Options on the
+command-line always take precedence over environment variable
+settings, however.
+
+Note that you may also permanently specify option values by placing
+option settings in the file @file{~/.ledgerrc}, for example:
+
+@example
+--cache /tmp/.mycache
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.84933999</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/143.snapshots b/doc/Ledger.scriv/snapshots/143.snapshots
new file mode 100644
index 00000000..bef7eddf
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/143.snapshots
@@ -0,0 +1,515 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>A period expression indicates a span of time, or a reporting interval,
+or both. The full syntax is:
+
+@example
+[INTERVAL] [BEGIN] [END]
+@end example
+
+The optional @var{INTERVAL} part may be any one of:
+
+@example
+every day
+every week
+every monthly
+every quarter
+every year
+every N days # N is any integer
+every N weeks
+every N months
+every N quarters
+every N years
+daily
+weekly
+biweekly
+monthly
+bimonthly
+quarterly
+yearly
+@end example
+
+After the interval, a begin time, end time, both or neither may be
+specified. As for the begin time, it can be either of:
+
+@example
+from &lt;SPEC&gt;
+since &lt;SPEC&gt;
+@end example
+
+The end time can be either of:
+
+@example
+to &lt;SPEC&gt;
+until &lt;SPEC&gt;
+@end example
+
+Where @var{SPEC} can be any of:
+
+@example
+2004
+2004/10
+2004/10/1
+10/1
+october
+oct
+this week # or day, month, quarter, year
+next week
+last week
+@end example
+
+The beginning and ending can be given at the same time, if it spans a
+single period. In that case, just use @var{SPEC} by itself. In that
+case, the period @samp{oct}, for example, will cover all the days in
+october. The possible forms are:
+
+@example
+&lt;SPEC&gt;
+in &lt;SPEC&gt;
+@end example
+
+Here are a few examples of period expressions:
+
+@example
+monthly
+monthly in 2004
+weekly from oct
+weekly from last month
+from sep to oct
+from 10/1 to 10/5
+monthly until 2005
+from apr
+until nov
+last oct
+weekly last august
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.859014</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/144.snapshots b/doc/Ledger.scriv/snapshots/144.snapshots
new file mode 100644
index 00000000..1011d207
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/144.snapshots
@@ -0,0 +1,576 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Format strings may be used to change the output format of reports.
+They are specified by passing a formatting string to the
+@option{--format} (@option{-F}) option. Within that string,
+constructs are allowed which make it possible to display the various
+parts of an account or posting in custom ways.
+
+Within a format strings, a substitution is specified using a percent
+character (@samp{%}). The basic format of all substitutions is:
+
+@example
+%[-][MIN WIDTH][.MAX WIDTH]EXPR
+@end example
+
+If the optional minus sign (@samp{-}) follows the percent character,
+whatever is substituted will be left justified. The default is right
+justified. If a minimum width is given next, the substituted text
+will be at least that wide, perhaps wider. If a period and a maximum
+width is given, the substituted text will never be wider than this,
+and will be truncated to fit. Here are some examples:
+
+@example
+%-P a transaction's payee, left justified
+%20P The same, right justified, at least 20 chars wide
+%.20P The same, no more than 20 chars wide
+%-.20P Left justified, maximum twenty chars wide
+@end example
+
+The expression following the format constraints can be a single
+letter, or an expression enclosed in parentheses or brackets. The
+allowable expressions are:
+
+@table @code
+@item %
+Inserts a percent sign.
+
+@item t
+Inserts the results of the value expression specified by @option{-t}.
+If @option{-t} was not specified, the current report style's value
+expression is used.
+
+@item T
+Inserts the results of the value expression specified by @option{-T}.
+If @option{-T} was not specified, the current report style's value
+expression is used.
+
+@item |
+Inserts a single space. This is useful if a width is specified, for
+inserting a certain number of spaces.
+
+@item _
+Inserts a space for each level of an account's depth. That is, if an
+account has two parents, this construct will insert two spaces. If a
+minimum width is specified, that much space is inserted for each level
+of depth. Thus @samp{%5_}, for an account with four parents, will
+insert twenty spaces.
+
+@item (EXPR)
+Inserts the amount resulting from the value expression given in
+parentheses. To insert five times the total value of an account, for
+example, one could say @samp{%12(5*O)}. Note: It's important to put
+the five first in that expression, so that the commodity doesn't get
+stripped from the total.
+
+@item [DATEFMT]
+Inserts the result of formatting a posting's date with a date
+format string, epostly like those supported by @code{strftime}. For
+example: @samp{%[%Y/%m/%d %H:%M:%S]}.
+
+@item S
+Insert the pathname of the file from which the transaction's data was read.
+
+@item B
+Inserts the beginning character position of that transaction within the file.
+
+@item b
+Inserts the beginning line of that transaction within the file.
+
+@item E
+Inserts the ending character position of that transaction within the file.
+
+@item e
+Inserts the ending line of that transaction within the file.
+
+@item D
+By default, this is the same as @samp{%[%Y/%m%/d]}. The date format
+used can be changed at any time with the @option{-y} flag, however.
+Using @samp{%D} gives the user more control over the way dates are
+output.
+
+@item d
+This is the same as the @samp{%D} option, unless the transaction has an
+effective date, in which case it prints
+@samp{[ACTUAL_DATE=EFFECtIVE_DATE]}.
+
+@item X
+If a posting has been cleared, this inserts @samp{*} followed by a
+space; otherwise nothing is inserted.
+
+@item Y
+This is the same as @samp{%X}, except that it only displays a state
+character if all of the member postings have the same state.
+
+@item C
+Inserts the checking number for a transaction, in parentheses, followed by
+a space; if none was specified, nothing is inserted.
+
+@item P
+Inserts the payee related to a posting.
+
+@item a
+Inserts the optimal short name for an account. This is normally used
+in balance reports. It prints a parent account's name if that name
+has not been printed yet, otherwise it just prints the account's name.
+
+@item A
+Inserts the full name of an account.
+
+@item W
+This is the same as @samp{%A}, except that it first displays the
+posting's state @emph{if the transaction's posting states are not
+all the same}, followed by the full account name. This is offered as
+a printing optimization, so that combined with @samp{%Y}, only the
+minimum amount of state detail is printed.
+
+@item o
+Inserts the ``optimized'' form of a posting's amount. This is
+used by the print report. In some cases, this inserts nothing; in
+others, it inserts the posting amount and its cost. It's use is
+not recommend unless you are modifying the print report.
+
+@item n
+Inserts the note associated with a posting, preceded by two spaces
+and a semi-colon, if it exists. Thus, no none becomes an empty
+string, while the note @samp{foo} is substituted as @samp{ ; foo}.
+
+@item N
+Inserts the note associated with a posting, if one exists.
+
+@item /
+The @samp{%/} construct is special. It separates a format string
+between what is printed for the first posting of a transaction, and
+what is printed for all subsequent postings. If not used, the
+same format string is used for all postings.
+@end table</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.868301</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/145.snapshots b/doc/Ledger.scriv/snapshots/145.snapshots
new file mode 100644
index 00000000..5b421bd1
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/145.snapshots
@@ -0,0 +1,479 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Value expressions are an expression language used by Ledger to
+calculate values used by the program for many different purposes:
+
+@enumerate
+@item
+The values displayed in reports
+@item
+For predicates (where truth is anything non-zero), to determine which
+postings are calculated (@option{-l}) or displayed (@option{-d}).
+@item
+For sorting criteria, to yield the sort key.
+@item
+In the matching criteria used by automated postings.
+@end enumerate
+
+Value expressions support most simple math and logic operators, in
+addition to a set of one letter functions and variables. A function's
+argument is whatever follows it. The following is a display predicate
+that I use with the @command{balance} command:
+
+@example
+ledger -d /^Liabilities/?T&lt;0:UT&gt;100 balance
+@end example
+
+The effect is that account totals are displayed only if: 1) A
+Liabilities account has a total less than zero; or 2) the absolute
+value of the account's total exceeds 100 units of whatever commodity
+contains. If it contains multiple commodities, only one of them must
+exceed 100 units.
+
+Display predicates are also very handy with register reports, to
+constrain which transactions are printed. For example, the following
+command shows only transactions from the beginning of the current month,
+while still calculating the running balance based on all transactions:
+
+@example
+ledger -d "d&gt;[this month]" register checking
+@end example
+
+This advantage to this command's complexity is that it prints the
+running total in terms of all transactions in the register. The following,
+simpler command is similar, but totals only the displayed
+postings:
+
+@example
+ledger -b "this month" register checking
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.87773201</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/146.snapshots b/doc/Ledger.scriv/snapshots/146.snapshots
new file mode 100644
index 00000000..c3b28f9e
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/146.snapshots
@@ -0,0 +1,455 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Below are the one letter variables available in any value expression.
+For the register and print commands, these variables relate to
+individual postings, and sometimes the account affected by a
+posting. For the balance command, these variables relate to
+accounts---often with a subtle difference in meaning. The use of each
+variable for both is specified.
+
+@table @code
+@item t
+This maps to whatever the user specified with @option{-t}. In a
+register report, @option{-t} changes the value column; in a balance
+report, it has no meaning by default. If @option{-t} was not
+specified, the current report style's value expression is used.
+
+@item T
+This maps to whatever the user specified with @option{-T}. In a
+register report, @option{-T} changes the totals column; in a balance
+report, this is the value given for each account. If @option{-T} was
+not specified, the current report style's value expression is used.
+
+@item m
+This is always the present moment/date.
+@end table</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.88695401</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/147.snapshots b/doc/Ledger.scriv/snapshots/147.snapshots
new file mode 100644
index 00000000..699ad68b
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/147.snapshots
@@ -0,0 +1,469 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@table @code
+@item d
+A posting's date, as the number of seconds past the epoch. This
+is always ``today'' for an account.
+
+@item a
+The posting's amount; the balance of an account, without
+considering children.
+
+@item b
+The cost of a posting; the cost of an account, without its
+children.
+
+@item v
+The market value of a posting, or an account without its children.
+
+@item g
+The net gain (market value minus cost basis), for a posting or an
+account without its children. It is the same as @samp{v-b}.
+
+@item l
+The depth (``level'') of an account. If an account has one parent,
+it's depth is one.
+
+@item n
+The index of a posting, or the count of postings affecting an
+account.
+
+@item X
+1 if a posting's transaction has been cleared, 0 otherwise.
+
+@item R
+1 if a posting is not virtual, 0 otherwise.
+
+@item Z
+1 if a posting is not automated, 0 otherwise.
+@end table</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.89628899</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/148.snapshots b/doc/Ledger.scriv/snapshots/148.snapshots
new file mode 100644
index 00000000..77407a10
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/148.snapshots
@@ -0,0 +1,454 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@table @code
+@item O
+The total of all postings seen so far, or the total of an account
+and all its children.
+
+@item N
+The total count of postings affecting an account and all its
+children.
+
+@item B
+The total cost of all postings seen so far; the total cost of an
+account and all its children.
+
+@item V
+The market value of all postings seen so far, or of an account and
+all its children.
+
+@item G
+The total net gain (market value minus cost basis), for a series of
+postings, or an account and its children. It is the same as
+@samp{V-B}.
+@end table</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.905615</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/149.snapshots b/doc/Ledger.scriv/snapshots/149.snapshots
new file mode 100644
index 00000000..f674d486
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/149.snapshots
@@ -0,0 +1,453 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The available one letter functions are:
+
+@table @code
+@item -
+Negates the argument.
+
+@item U
+The absolute (unsigned) value of the argument.
+
+@item S
+Strips the commodity from the argument.
+
+@item A
+The arithmetic mean of the argument; @samp{Ax} is the same as
+@samp{x/n}.
+
+@item P
+The present market value of the argument. The syntax @samp{P(x,d)} is
+supported, which yields the market value at time @samp{d}. If no date
+is given, then the current moment is used.
+@end table</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.91490099</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/15.snapshots b/doc/Ledger.scriv/snapshots/15.snapshots
new file mode 100644
index 00000000..ffb71fad
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/15.snapshots
@@ -0,0 +1,441 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>If you need help on how to use Ledger, or run into problems, you can
+just the Ledger mailing list at the following Web address:
+
+@example
+https://lists.sourceforge.net/lists/listinfo/ledger-discuss
+@end example
+
+You can also find help at the @samp{#ledger} channel on the IRC server
+@samp{irc.freenode.net}.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.69604799</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/150.snapshots b/doc/Ledger.scriv/snapshots/150.snapshots
new file mode 100644
index 00000000..9a88e87a
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/150.snapshots
@@ -0,0 +1,440 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The binary and ternary operators, in order of precedence, are:
+
+@enumerate
+@item @samp{* /}
+@item @samp{+ -}
+@item @samp{! &lt; &gt; =}
+@item @samp{&amp; | ?:}
+@end enumerate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.92411399</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/151.snapshots b/doc/Ledger.scriv/snapshots/151.snapshots
new file mode 100644
index 00000000..bd4fef8f
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/151.snapshots
@@ -0,0 +1,475 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>More complicated expressions are possible using:
+
+@table @code
+@item NUM
+A plain integer represents a commodity-less amount.
+
+@item @{AMOUNT@}
+An amount in braces can be any kind of amount supported by ledger,
+with or without a commodity. Use this for decimal values.
+
+@item /REGEXP/
+@item W/REGEXP/
+A regular expression that matches against an account's full name. If
+a posting, this will match against the account affected by the
+posting.
+
+@item //REGEXP/
+@item p/REGEXP/
+A regular expression that matches against a transaction's payee name.
+
+@item ///REGEXP/
+@item w/REGEXP/
+A regular expression that matches against an account's base name. If
+a posting, this will match against the account affected by the
+posting.
+
+@item c/REGEXP/
+A regular expression that matches against the transaction code (the text
+that occurs between parentheses before the payee name).
+
+@item e/REGEXP/
+A regular expression that matches against a posting's note, or
+comment field.
+
+@item (EXPR)
+A sub-expression is nested in parenthesis. This can be useful passing
+more complicated arguments to functions, or for overriding the natural
+precedence order of operators.
+
+@item [DATE]
+Useful specifying a date in plain terms. For example, you could say
+@samp{[2004/06/01]}.
+@end table</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.933642</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/152.snapshots b/doc/Ledger.scriv/snapshots/152.snapshots
new file mode 100644
index 00000000..2e4ae1c8
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/152.snapshots
@@ -0,0 +1,558 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The ledger file format is quite simple, but also very flexible. It
+supports many options, though typically the user can ignore most of
+them. They are summarized below.
+
+The initial character of each line determines what the line means, and
+how it should be interpreted. Allowable initial characters are:
+
+@table @code
+@item NUMBER
+A line beginning with a number denotes a transaction. It may be followed
+by any number of lines, each beginning with whitespace, to denote the
+transaction's account postings. The format of the first line is:
+
+@example
+DATE[=EDATE] [*|!] [(CODE)] DESC
+@end example
+
+If @samp{*} appears after the date (with optional effective date), it
+indicates the transaction is ``cleared'', which can mean whatever the user
+wants it t omean. If @samp{!} appears after the date, it indicates d
+the transaction is ``pending''; i.e., tentatively cleared from the user's
+point of view, but not yet actually cleared. If a @samp{CODE} appears
+in parentheses, it may be used to indicate a check number, or the type
+of the posting. Following these is the payee, or a description of
+the posting.
+
+The format of each following posting is:
+
+@example
+ ACCOUNT AMOUNT [; NOTE]
+@end example
+
+The @samp{ACCOUNT} may be surrounded by parentheses if it is a virtual
+postings, or square brackets if it is a virtual postings that
+must balance. The @samp{AMOUNT} can be followed by a per-unit
+posting cost, by specifying @samp{@@ AMOUNT}, or a complete
+posting cost with @samp{@@@@ AMOUNT}. Lastly, the @samp{NOTE} may
+specify an actual and/or effective date for the posting by using
+the syntax @samp{[ACTUAL_DATE]} or @samp{[=EFFECTIVE_DATE]} or
+@samp{[ACTUAL_DATE=EFFECtIVE_DATE]}.
+
+@item =
+An automated transaction. A value expression must appear after the equal
+sign.
+
+After this initial line there should be a set of one or more
+postings, just as if it were normal transaction. If the amounts of the
+postings have no commodity, they will be applied as modifiers to
+whichever real posting is matched by the value expression.
+
+@item ~
+A period transaction. A period expression must appear after the tilde.
+
+After this initial line there should be a set of one or more
+postings, just as if it were normal transaction.
+
+@item !
+A line beginning with an exclamation mark denotes a command directive.
+It must be immediately followed by the command word. The supported
+commands are:
+
+@table @samp
+@item !include
+Include the stated ledger file.
+
+@item !account
+The account name is given is taken to be the parent of all
+postings that follow, until @samp{!end} is seen.
+
+@item !end
+Ends an account block.
+@end table
+
+@item ;
+A line beginning with a colon indicates a comment, and is ignored.
+
+@item Y
+If a line begins with a capital Y, it denotes the year used for all
+subsequent transactions that give a date without a year. The year should
+appear immediately after the Y, for example: @samp{Y2004}. This is
+useful at the beginning of a file, to specify the year for that file.
+If all transactions specify a year, however, this command has no effect.
+
+@item P
+Specifies a historical price for a commodity. These are usually found
+in a pricing history file (see the @option{-Q} option). The syntax
+is:
+@example
+P DATE SYMBOL PRICE
+@end example
+
+@item N SYMBOL
+Indicates that pricing information is to be ignored for a given
+symbol, nor will quotes ever be downloaded for that symbol. Useful
+with a home currency, such as the dollar ($). It is recommended that
+these pricing options be set in the price database file, which
+defaults to @file{~/.pricedb}. The syntax for this command is:
+@example
+N SYMBOL
+@end example
+
+@item D AMOUNT
+Specifies the default commodity to use, by specifying an amount in the
+expected format. The @command{transaction} command will use this commodity
+as the default when none other can be determined. This command may be
+used multiple times, to set the default flags for different
+commodities; whichever is seen last is used as the default commodity.
+For example, to set US dollars as the default commodity, while also
+setting the thousands flag and decimal flag for that commodity, use:
+@example
+D $1,000.00
+@end example
+
+@item C AMOUNT1 = AMOUNT2
+Specifies a commodity conversion, where the first amount is given to
+be equivalent to the second amount. The first amount should use the
+decimal precision desired during reporting:
+@example
+C 1.00 Kb = 1024 bytes
+@end example
+
+@item i, o, b, h
+These four relate to timeclock support, which permits ledger to read
+timelog files. See the timeclock's documentation for more info on the
+syntax of its timelog files.
+@end table</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.94292599</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/153.snapshots b/doc/Ledger.scriv/snapshots/153.snapshots
new file mode 100644
index 00000000..81129586
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/153.snapshots
@@ -0,0 +1,472 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>This chapter presents a series of recipes, gradually introducing all of
+the command-line features of Ledger.
+
+For the purpose of these examples, assume the environment variable
+@var{LEDGER} is set to the file @file{sample.dat} (which is included
+in the distribution), and that the contents of that file are:
+
+@smallexample
+= /^Expenses:Books/
+ (Liabilities:Taxes) -0.10
+
+~ Monthly
+ Assets:Bank:Checking $500.00
+ Income:Salary
+
+2004/05/01 * Checking balance
+ Assets:Bank:Checking $1,000.00
+ Equity:Opening Balances
+
+2004/05/01 * Investment balance
+ Assets:Brokerage 50 AAPL @@ $30.00
+ Equity:Opening Balances
+
+2004/05/14 * Pay day
+ Assets:Bank:Checking $500.00
+ Income:Salary
+
+2004/05/27 Book Store
+ Expenses:Books $20.00
+ Liabilities:MasterCard
+
+2004/05/27 (100) Credit card company
+ Liabilities:MasterCard $20.00
+ Assets:Bank:Checking
+@end smallexample
+
+This sample file demonstrates a basic principle of accounting which it
+is recommended you follow: Keep all of your accounts under five parent
+Assets, Liabilities, Income, Expenses and Equity. It is important to
+do so in order to make sense out of the following examples.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.95243299</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/155.snapshots b/doc/Ledger.scriv/snapshots/155.snapshots
new file mode 100644
index 00000000..8986d45e
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/155.snapshots
@@ -0,0 +1,515 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Ledger has seven basic commands, but by far the most often used are
+@command{balance} and @command{register}. To see a summary balance of
+all accounts, use:
+
+@example
+ledger bal
+@end example
+
+@command{bal} is a short-hand for @command{balance}. This command
+prints out the summary totals of the five parent accounts used in
+@file{sample.dat}:
+
+@smallexample
+ $1,480.00
+ 50 AAPL Assets
+ $-2,500.00 Equity
+ $20.00 Expenses
+ $-500.00 Income
+ $-2.00 Liabilities
+--------------------
+ $-1,502.00
+ 50 AAPL
+@end smallexample
+
+None of the child accounts are shown, just the parent account totals.
+We can see that in @samp{Assets} there is $1,480.00, and 50 shares of
+Apple stock. There is also a negative grand total. Usually the grand
+total is zero, which means that all accounts balance@footnote{It is
+impossible for accounts not to balance in ledger; it reports an error
+if a posting does not balance}. In this case, since the 50 shares
+of Apple stock cost $1,500.00 dollars, then these two amounts balance
+each other in the grand total. The extra $2.00 comes from a virtual
+posting being added by the automatic transaction at the top of the file.
+The transaction is virtual because the account name was surrounded by
+parentheses in an automatic transaction. Automatic transactions will be
+discussed later, but first let's remove the virtual posting from
+the balance report by using the @option{--real} option:
+
+@example
+ledger --real bal
+@end example
+
+Now the report is:
+
+@smallexample
+ $1,480.00
+ 50 AAPL Assets
+ $-2,500.00 Equity
+ $20.00 Expenses
+ $-500.00 Income
+--------------------
+ $-1,500.00
+ 50 AAPL
+@end smallexample
+
+Since the liability was a virtual posting, it has dropped from the
+report and we see that final total is balanced.
+
+But we only know that it balances because @file{sample.dat} is quite
+simple, and we happen to know that the 50 shares of Apple stock cost
+$1,500.00. We can verify that things really balance by reporting the
+Apple shares in terms of their cost, instead of their quantity. To do
+this requires the @option{--basis}, or @option{-B}, option:
+
+@example
+ledger --real -B bal
+@end example
+
+This command reports:
+
+@smallexample
+ $2,980.00 Assets
+ $-2,500.00 Equity
+ $20.00 Expenses
+ $-500.00 Income
+@end smallexample
+
+With the basis cost option, the grand total has disappeared, as it is
+now zero. The confirms that the cost of everything balances to zero,
+@emph{which must always be true}. Reporting the real basis cost
+should never yield a remainder@footnote{If it ever does, then
+generated postings are involved, which can be removed using
+@option{--actual}}.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.96237299</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/156.snapshots b/doc/Ledger.scriv/snapshots/156.snapshots
new file mode 100644
index 00000000..99b56ac0
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/156.snapshots
@@ -0,0 +1,484 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The totals reported by the balance command are only the topmost parent
+accounts. To see the totals of all child accounts as well, use the
+@option{-s} option:
+
+@example
+ledger --real -B -s bal
+@end example
+
+This reports:
+
+@smallexample
+ $2,980.00 Assets
+ $1,480.00 Bank:Checking
+ $1,500.00 Brokerage
+ $-2,500.00 Equity:Opening Balances
+ $20.00 Expenses:Books
+ $-500.00 Income:Salary
+@end smallexample
+
+This shows that the @samp{Assets} total is made up from two child
+account, but that the total for each of the other accounts comes from
+one child account.
+
+Sometimes you may have a lot of children, nested very deeply, but only
+want to report the first two levels. This can be done with a display
+predicate, using a value expression. In the value expression,
+@code{T} represents the reported total, and @code{l} is the display
+level for the account:
+
+@example
+ledger --real -B -d "T&amp;l&lt;=2" bal
+@end example
+
+This reports:
+
+@smallexample
+ $2,980.00 Assets
+ $1,480.00 Bank
+ $1,500.00 Brokerage
+ $-2,500.00 Equity:Opening Balances
+ $20.00 Expenses:Books
+ $-500.00 Income:Salary
+@end smallexample
+
+Instead of reporting @samp{Bank:Checking} as a child of @samp{Assets},
+it report only @samp{Bank}, since that account is a nesting level of
+2, while @samp{Checking} is at level 3.
+
+To review the display predicate used---@code{T&amp;l&lt;=2}---this rather
+terse expression means: Display an account only if it has a non-zero
+total (@code{T}), and its nesting level is less than or equal to 2
+(@code{l&lt;=2}).</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.97188601</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/157.snapshots b/doc/Ledger.scriv/snapshots/157.snapshots
new file mode 100644
index 00000000..bd79e73a
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/157.snapshots
@@ -0,0 +1,478 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>While reporting the totals for all accounts can be useful, most often
+you will want to check the balance of a specific account or accounts.
+To do this, put one or more account names after the balance command.
+Since these names are really regular expressions, you can use partial
+names if you wish:
+
+@example
+ledger bal checking
+@end example
+
+Reports:
+
+@smallexample
+ $1,480.00 Assets:Bank:Checking
+@end smallexample
+
+Any number of names may be used:
+
+@example
+ledger bal checking broker liab
+@end example
+
+Reports:
+
+@smallexample
+ $1,480.00 Assets:Bank:Checking
+ 50 AAPL Assets:Brokerage
+ $-2.00 Liabilities
+@end smallexample
+
+In this case no grand total is reported, because you are asking for
+specific account balances.
+
+For those comfortable with regular expressions, any Perl regexp is
+allowed:
+
+@example
+ledger bal ^assets.*checking ^liab
+@end example
+
+Reports:
+
+@smallexample
+ $1,480.00 Assets:Bank:Checking
+ $-2.00 Liabilities:Taxes
+@end smallexample</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.98177099</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/158.snapshots b/doc/Ledger.scriv/snapshots/158.snapshots
new file mode 100644
index 00000000..96039b1d
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/158.snapshots
@@ -0,0 +1,497 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>While the @command{balance} command can be very handy for checking
+account totals, by far the most powerful of Ledger's reporting tools
+is the @command{register} command. In fact, internally both commands
+use the same logic, but report the results differently:
+@command{balance} shows the summary totals, while @command{register}
+reports each posting and how it contributes to that total.
+
+Paradoxically, the most basic form of @command{register} is almost
+never used, since it displays every posting:
+
+@example
+ledger reg
+@end example
+
+@command{reg} is a short-hand for @command{register}. This command
+reports:
+
+@smallexample
+2004/05/01 Checking balance Assets:Bank:Checking $1,000.00 $1,000.00
+ Equity:Opening Balan.. $-1,000.00 0
+2004/05/01 Investment balance Assets:Brokerage 50 AAPL 50 AAPL
+ Equity:Opening Balan.. $-1,500.00 $-1,500.00
+ 50 AAPL
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $-1,000.00
+ 50 AAPL
+ Income:Salary $-500.00 $-1,500.00
+ 50 AAPL
+2004/05/27 Book Store Expenses:Books $20.00 $-1,480.00
+ 50 AAPL
+ Liabilities:MasterCard $-20.00 $-1,500.00
+ 50 AAPL
+ (Liabilities:Taxes) $-2.00 $-1,502.00
+ 50 AAPL
+2004/05/27 Credit card company Liabilities:MasterCard $20.00 $-1,482.00
+ 50 AAPL
+ Assets:Bank:Checking $-20.00 $-1,502.00
+ 50 AAPL
+@end smallexample
+
+This rather verbose output shows every account posting in
+@file{sample.dat}, and how it affects the running total. The final
+total is identical to what we saw with the plain @command{balance}
+command. To see how things really balance, we can use @samp{--real
+-B}, just as we did with @command{balance}:
+
+@example
+ledger --real -B reg
+@end example
+
+Reports:
+
+@smallexample
+2004/05/01 Checking balance Assets:Bank:Checking $1,000.00 $1,000.00
+ Equity:Opening Balan.. $-1,000.00 0
+2004/05/01 Investment balance Assets:Brokerage $1,500.00 $1,500.00
+ Equity:Opening Balan.. $-1,500.00 0
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $500.00
+ Income:Salary $-500.00 0
+2004/05/27 Book Store Expenses:Books $20.00 $20.00
+ Liabilities:MasterCard $-20.00 0
+2004/05/27 Credit card company Liabilities:MasterCard $20.00 $20.00
+ Assets:Bank:Checking $-20.00 0
+@end smallexample
+
+Here we see that everything balances to zero in the end, as it must.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.99077201</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/159.snapshots b/doc/Ledger.scriv/snapshots/159.snapshots
new file mode 100644
index 00000000..a870deef
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/159.snapshots
@@ -0,0 +1,464 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The most common use of the register command is to summarize
+postings based on the account(s) they affect. Using
+@file{sample.dat} as as example, we could look at all book purchases
+using:
+
+@example
+ledger reg books
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 Book Store Expenses:Books $20.00 $20.00
+@end smallexample
+
+If a double-dash (@samp{--}) occurs in the list of regular
+expressions, any following arguments are matched against payee names,
+instead of account names:
+
+@example
+ledger reg ^liab -- credit
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 Credit card company Liabilities:MasterCard $20.00 $20.00
+@end smallexample
+
+There are many reporting options for tailoring which postings are
+found, and also how to summarize the various amounts and totals that
+result. These are plumbed in greater depth below.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.000245</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/16.snapshots b/doc/Ledger.scriv/snapshots/16.snapshots
new file mode 100644
index 00000000..7a3a097d
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/16.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter Quick Reference</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.700744</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/160.snapshots b/doc/Ledger.scriv/snapshots/160.snapshots
new file mode 100644
index 00000000..70e4e512
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/160.snapshots
@@ -0,0 +1,439 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Although the easiest way to use the register is to report all the
+postings affecting a set of accounts, it can often result in more
+information than you want. To cope with an ever-growing amount of
+data, there are several options which can help you pinpoint your
+report to epostly the postings that interest you most. This is
+called the ``calculation'' phase of Ledger. All of its related
+options are documented under @option{--help-calc}.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.00958899</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/161.snapshots b/doc/Ledger.scriv/snapshots/161.snapshots
new file mode 100644
index 00000000..d4e8a7cf
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/161.snapshots
@@ -0,0 +1,520 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@c -c, --current show only current and past transactions (not future)
+
+@option{--current}(@option{-c}) displays transactions occurring on or
+before the current date. Any transaction recorded for a future date will be
+ignored, as if it had not been seen. This is useful if you happen to
+pre-record transactions, but still wish to view your balances in terms of
+what is available today.
+
+@c -b, --begin DATE set report begin date
+@c -e, --end DATE set report end date
+
+@option{--begin DATE} (@option{-b DATE}) limits the report to only
+those transactions occurring on or after @var{DATE}. The running total in
+the register will start at zero with the first posting, even if
+there are earlier transactions.
+
+To limit the display only, but still add earlier postings to the
+running total, use the display expression @samp{-d 'd&gt;=[DATE]'}):
+
+@example
+ledger --basis -b may -d 'd&gt;=[5/14]' reg ^assets
+@end example
+
+Reports:
+
+@smallexample
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $3,000.00
+2004/05/27 Credit card company Assets:Bank:Checking $-20.00 $2,980.00
+@end smallexample
+
+In this example, the displayed postings start from @samp{5/14},
+but the calculated total starts from the beginning of @samp{may}.
+
+@option{--end DATE} (@option{-e DATE}) states when reporting should
+end, both calculation and display. The ending date is inclusive.
+
+The @var{DATE} argument to the @option{-b} and @option{-e} options can
+be rather flexible. Assuming the current date to be November 15,
+2004, then all of the following are equivalent:
+
+@example
+ledger -b oct bal
+ledger -b "this oct" bal
+ledger -b 2004/10 bal
+ledger -b 10 bal
+ledger -b last bal
+ledger -b "last month" bal
+@end example
+
+@c -p, --period STR report using the given period
+@c --period-sort EXPR sort each report period's transactions by EXPR
+
+To constrain the report to a specific time period, use
+@option{--period} (@option{-p}). A time period may have both a
+beginning and an end, or neither, as well as a specified interval.
+Here are a few examples:
+
+@example
+ledger -p 2004 bal
+ledger -p august bal
+ledger -p "from aug to oct" bal
+ledger -p "daily from 8/1 to 8/15" bal
+ledger -p "weekly since august" bal
+ledger -p "monthly from feb to oct" bal
+ledger -p "quarterly in 2004" bal
+ledger -p yearly bal
+@end example
+
+See @ref{Period expressions} for more on syntax. Also, all of the
+options @option{-b}, @option{-e} and @option{-p} may be used together,
+but whatever information occurs last takes priority. An example of
+such usage (in a script, perhaps) would be:
+
+@example
+ledger -b 2004 -e 2005 -p monthly reg ^expenses
+@end example
+
+This command is identical to:
+
+@example
+ledger -p "monthly in 2004" reg ^expenses
+@end example
+
+The postings within a period may be sorted using
+@option{--period-sort}, which takes a value expression. This is
+similar to the @option{--sort} option, except that it sorts within
+each period transaction, rather than sorting all postings in the report.
+See the documentation on @option{--sort} below for more details.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.018765</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/162.snapshots b/doc/Ledger.scriv/snapshots/162.snapshots
new file mode 100644
index 00000000..6e89947b
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/162.snapshots
@@ -0,0 +1,473 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>By default, all regular postings are included in each report. To
+limit the report to certain kinds of postings, use one or more of
+the following options:
+
+@table @option
+@item -C, --cleared
+Consider only cleared postings.
+@item -U, --uncleared
+Consider only uncleared and pending postings.
+@item -R, --real
+Consider only real (non-virtual) postings.
+@item -L, --actual
+Consider only actual (non-automated) postings.
+@end table
+
+Cleared postings are indicated by an asterix placed just before
+the payee name in a posting. The meaning of this flag is up to
+the user, but typically it means that a transaction has been seen on a
+financial statement. Pending postings use an exclamation mark in
+the same position, but are mainly used only by reconciling software.
+Uncleared postings are for things like uncashed checks, credit
+charges that haven't appeared on a statement yet, etc.
+
+Real postings are all non-virtual postings, where the account
+name is not surrounded by parentheses or square brackets. Virtual
+postings are useful for showing a transfer of money that never
+really happened, like money set aside for savings without actually
+transferring it from the parent account.
+
+Actual postings are those not generated, either as part of an
+automated transaction, or a budget or forecast report. A useful of when you
+might like to filter out generated postings is with a budget:
+
+@example
+ledger --budget --actual reg ^expenses
+@end example
+
+This command outputs all postings affecting a budgeted account,
+but without subtracting the budget amount (because the generated
+postings are suppressed with @option{--actual}). The report shows
+how much you actually spent on budgeted items.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.028871</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/164.snapshots b/doc/Ledger.scriv/snapshots/164.snapshots
new file mode 100644
index 00000000..58c99d43
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/164.snapshots
@@ -0,0 +1,462 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@c -r, --related calculate report using related postings
+
+Normally, a register report includes only the postings that match
+the regular expressions specified after the command word. For
+example, to report all expenses:
+
+@example
+ledger reg ^expenses
+@end example
+
+This reports:
+
+@smallexample
+2004/05/29 Book Store Expenses:Books $20.00 $20.00
+@end smallexample
+
+Using @option{--related} (@option{-r}) reports the postings that
+did not match your query, but only in transactions that otherwise would
+have matched. This has the effect of indicating where money came
+from, or when to:
+
+@example
+ledger -r reg ^expenses
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 Book Store Liabilities:MasterCard $20.00 $20.00
+@end smallexample</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.03813499</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/165.snapshots b/doc/Ledger.scriv/snapshots/165.snapshots
new file mode 100644
index 00000000..e784c5b8
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/165.snapshots
@@ -0,0 +1,529 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@c --budget generate budget transactions based on FILE
+
+There is more information about budgeting and forecasting in
+@ref{Budgeting and forecasting}. Basically, if you have any period
+transactions in your ledger file, you can use these options. A period
+transaction looks like:
+
+@example
+~ Monthly
+ Assets:Bank:Checking $500.00
+ Income:Salary
+@end example
+
+The difference from a regular transaction is that the first line begins with
+a tilde (~), and instead of a payee there's a period expression
+(@ref{Period expressions}). Otherwise, a period transaction is in every
+other way the same as a regular transaction.
+
+With such a transaction in your ledger file, the @option{--budget} option
+will report only postings that match a budgeted account. Using
+@file{sample.dat} from above:
+
+@example
+ledger --budget reg ^income
+@end example
+
+Reports:
+
+@smallexample
+2004/05/01 Budget transaction Income:Salary $500.00 $500.00
+2004/05/14 Pay day Income:Salary $-500.00 0
+@end smallexample
+
+The final total is zero, indicating that the budget matched epostly
+for the reported period. Budgeting is most often helpful with period
+reporting; for example, to show monthly budget results use
+@option{--budget -p monthly}.
+
+@c --add-budget show all postings plus the budget
+@c --unbudgeted show only unbudgeted postings
+
+The @option{--add-budget} option reports all matching postings in
+addition to budget postings; while @option{--unbudgeted} shows
+only those that don't match a budgeted account. To summarize:
+
+@table @option
+@item --budget
+Show postings matching budgeted accounts.
+@item --unbudgeted
+Show postings matching unbudgeted accounts.
+@item --add-budget
+Show both budgeted and unbudgeted postings together (i.e., add the
+generated budget postings to the regular report).
+@end table
+
+@c --forecast EXPR generate forecast transactions while EXPR is true
+
+A report with the @option{--forecast} option will add budgeted
+postings while the specified value expression is true. For
+example:
+
+@example
+ledger --forecast 'd&lt;[2005] reg ^income
+@end example
+
+Reports:
+
+@smallexample
+2004/05/14 Pay day Income:Salary $-500.00 $-500.00
+2004/12/01 Forecast transaction Income:Salary $-500.00 $-1,000.00
+2005/01/01 Forecast transaction Income:Salary $-500.00 $-1,500.00
+@end smallexample
+
+The date this report was made was November 5, 2004; the reason the
+first forecast transaction is in december is that forecast transactions are only
+added for the future, and they only stop after the value expression
+has matched at least once, which is why the January transaction appears. A
+forecast report can be very useful for determining when money will run
+out in an account, or for projecting future cash flow:
+
+@example
+ledger --forecast 'd&lt;[2008]' -p yearly reg ^inc ^exp
+@end example
+
+This reports balances projected income against projected expenses,
+showing the resulting total in yearly intervals until 2008. For the
+case of @file{sample.dat}, which has no budgeted expenses, the result
+of the above command (in November 2004) is:
+
+@smallexample
+2004/01/01 - 2004/12/31 Income:Salary $-1,000.00 $-1,000.00
+ Expenses:Books $20.00 $-980.00
+2005/01/01 - 2005/12/31 Income:Salary $-6,000.00 $-6,980.00
+2006/01/01 - 2006/12/31 Income:Salary $-6,000.00 $-12,980.00
+2007/01/01 - 2007/12/31 Income:Salary $-6,000.00 $-18,980.00
+2008/01/01 - 2008/01/01 Income:Salary $-500.00 $-19,480.00
+@end smallexample</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.04741499</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/166.snapshots b/doc/Ledger.scriv/snapshots/166.snapshots
new file mode 100644
index 00000000..7ae6543d
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/166.snapshots
@@ -0,0 +1,469 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@c -l, --limit EXPR calculate only postings matching EXPR
+
+Value expressions can be quite complex, and are treated more fully in
+@ref{Value expressions}. They can be used for limiting a report with
+@option{--limit} (@option{-l}). The following command report income
+since august, but expenses since october:
+
+@example
+ledger -l '(/income/&amp;d&gt;=[aug])|(/expenses/&amp;d&gt;=[oct])' reg
+@end example
+
+The basic form of this value expression is @samp{(A&amp;B)|(A&amp;B)}. The
+@samp{A} in each part matches against an account name with
+@samp{/name/}, while each @samp{B} part compares the date of the
+posting (@samp{d}) with a specified month. The resulting report
+will contain only postings which match the value expression.
+
+@c -t, --amount EXPR use EXPR to calculate the displayed amount
+@c -T, --total EXPR use EXPR to calculate the displayed total
+
+Another use of value expressions is to calculate the amount reported
+for each line of a register report, or for computing the subtotal of
+each account shown in a balance report. This example divides each
+posting amount by two:
+
+@example
+ledger -t 'a/2' reg ^exp
+@end example
+
+The @option{-t} option doesn't affect the running total, only how the
+posting amount is displayed. To change the running total, use
+@option{-T}. In that case, you will likely want to use the total
+(@samp{O}) instead of the amount (@samp{a}):
+
+@example
+ledger -T 'O/2' reg ^exp
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.06326401</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/168.snapshots b/doc/Ledger.scriv/snapshots/168.snapshots
new file mode 100644
index 00000000..06040135
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/168.snapshots
@@ -0,0 +1,438 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Even after filtering down your data to just the postings you're
+interested in, the default reporting method of one posting per
+line is often still too much. To combat this complexity, it is
+possible to ask Ledger to report the details to you in many different
+forms, summarized in various ways. This is the ``display'' phase of
+Ledger, and is documented under @option{--help-disp}.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.07240999</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/169.snapshots b/doc/Ledger.scriv/snapshots/169.snapshots
new file mode 100644
index 00000000..96893461
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/169.snapshots
@@ -0,0 +1,535 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@c -n, --collapse register: collapse transactions with multiple postings
+
+When multiple postings relate to a single transaction, they are reported
+as part of that transaction. For example, in the case of @file{sample.dat}:
+
+@example
+ledger reg -- book
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 Book Store Expenses:Books $20.00 $20.00
+ Liabilities:MasterCard $-20.00 0
+ (Liabilities:Taxes) $-2.00 $-2.00
+@end smallexample
+
+All three postings are part of one transaction, and as such the transaction
+details are printed only once. To report every transaction on a single
+line, use @option{-n} to collapse transactions with multiple postings:
+
+@example
+ledger -n reg -- book
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 Book Store &lt;Total&gt; $-2.00 $-2.00
+@end smallexample
+
+In the balance report, @option{-n} causes the grand total not to be
+displayed at the bottom of the report.
+
+@c -s, --subtotal balance: show sub-accounts; other: show subtotals
+
+If an account occurs more than once in a report, it is possible to
+combine them all and report the total per-account, using @option{-s}.
+For example, this command:
+
+@example
+ledger -B reg ^assets
+@end example
+
+Reports:
+
+@smallexample
+2004/05/01 Checking balance Assets:Bank:Checking $1,000.00 $1,000.00
+2004/05/01 Investment balance Assets:Brokerage $1,500.00 $2,500.00
+2004/05/14 Pay day Assets:Bank:Checking $500.00 $3,000.00
+2004/05/27 Credit card company Assets:Bank:Checking $-20.00 $2,980.00
+@end smallexample
+
+But if the @option{-s} option is added, the result becomes:
+
+@smallexample
+2004/05/01 - 2004/05/29 Assets:Bank:Checking $1,480.00 $1,480.00
+ Assets:Brokerage $1,500.00 $2,980.00
+@end smallexample
+
+When account subtotaling is used, only one transaction is printed, and the
+date and name reflect the range of the combined postings.
+
+@c -P, --by-payee show summarized totals by payee
+
+With @option{-P}, postings relating to the same payee are
+combined. In this case, the date of the combined transaction is that of the
+latest posting.
+
+@c -x, --comm-as-payee set commodity name as the payee, for reporting
+
+@option{-x} changes the payee name for each posting to be the same
+as the commodity it uses. This can be especially useful combined with
+other options, like @option{-P}. For example:
+
+@example
+ledger -Px reg ^assets
+@end example
+
+Reports:
+
+@smallexample
+2004/05/29 $ Assets:Bank:Checking $1,480.00 $1,480.00
+2004/05/01 AAPL Assets:Brokerage 50 AAPL $1,480.00
+ 50 AAPL
+@end smallexample
+
+This reports shows the subtotal for each commodity held, and where it
+is located. To see the basis cost, or initial investment, add
+@option{-B}. Applied to the example above:
+
+@smallexample
+2004/05/29 $ Assets:Bank:Checking $1,480.00 $1,480.00
+2004/05/01 AAPL Assets:Brokerage $1,500.00 $2,980.00
+@end smallexample
+
+@c -E, --empty balance: show accounts with zero balance
+
+The only other options which affect summarized totals is @option{-E},
+which works only in the balance report. In this case, it shows
+matching accounts with a zero a balance, which are ordinarily
+excluded. This can be useful to see all the accounts involved in a
+report, even if some have no total.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.08146301</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/17.snapshots b/doc/Ledger.scriv/snapshots/17.snapshots
new file mode 100644
index 00000000..ebf6ce0b
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/17.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter Ledger Tutorial</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.94787201</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/170.snapshots b/doc/Ledger.scriv/snapshots/170.snapshots
new file mode 100644
index 00000000..578404e6
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/170.snapshots
@@ -0,0 +1,462 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Although the @option{-p} option (also @option{--period}) is much more
+versatile, there are other options to make the most common period
+reports easier:
+
+@table @option
+@item -W, --weekly
+Show weekly sub-totals. Same as @samp{-p weekly}.
+@item -M, --monthly
+Show monthly sub-totals. Same as @samp{-p monthly}.
+@item -Y, --yearly
+Show yearly sub-totals. Same as @samp{-p yearly}.
+@end table
+
+@c --dow show a days-of-the-week report
+
+There is one kind of period report cannot be done with @option{-p}.
+This is the @option{--dow}, or ``days of the week'' report, which
+shows summarized totals for each day of the week. The following
+examples shows a ``day of the week'' report of income and expenses:
+
+@example
+ledger --dow reg ^inc ^exp
+@end example
+
+Reports:
+
+@smallexample
+2004/05/27 Thursdays Expenses:Books $20.00 $20.00
+2004/05/14 Fridays Income:Salary $-500.00 $-480.00
+@end smallexample</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.09072101</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/171.snapshots b/doc/Ledger.scriv/snapshots/171.snapshots
new file mode 100644
index 00000000..5cc4784b
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/171.snapshots
@@ -0,0 +1,486 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@c -S, --sort EXPR sort report according to the value expression EXPR
+
+The postings displayed in a report are shown in the same order as
+they appear in the ledger file. To change the order and sort a
+report, use the @option{--sort} option. @option{--sort} takes a value
+expression to determine the value to sort against, making it possible
+to sort according to complex criteria. Here are some simple and
+useful examples:
+
+@example
+ledger --sort d reg ^exp # sort by date
+ledger --sort t reg ^exp # sort by amount total
+ledger --sort -t reg ^exp # reverse sort by amount total
+ledger --sort Ut reg ^exp # sort by abs amount total
+@end example
+
+For the balance report, you will want to use @samp{T} instead of
+@samp{t}:
+
+@example
+ledger --sort T reg ^exp # sort by amount total
+ledger --sort -T reg ^exp # reverse sort by amount total
+ledger --sort UT reg ^exp # sort by abs amount total
+@end example
+
+The @option{--sort} options sorts all postings in a report. If
+periods are used (such as @option{--monthly}), this can get somewhat
+confusing. In that case, you'll probably want to sort within periods
+using @option{--period-sort} instead of @option{--sort}.
+
+@c -w, --wide for the default register report, use 132 columns
+
+And if the register seems too cramped, and you have a lot of screen
+real estate, you can use @option{-w} to format the report within 132
+acolumns, instead of 80. You are more likely then to see full payee
+and account names, as well as properly formatted totals when
+long-named commodities are used.
+
+If you want only the first or last N transactions to be printed---which can
+be very useful for viewing the last 10 transactions in your checking
+account, while also showing the cumulative balance from all
+transactions---use the @option{--head} and/or @option{--tail} options. The
+two options may be used simultaneously, for example:
+
+@example
+ledger --tail 20 reg checking
+@end example
+
+If the output from your command is very long, Ledger can output the
+data to a pager utility, such as @command{more} or @command{less}:
+
+@example
+ledger --pager /usr/bin/less reg checking
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.10013101</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/172.snapshots b/doc/Ledger.scriv/snapshots/172.snapshots
new file mode 100644
index 00000000..0ad5446a
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/172.snapshots
@@ -0,0 +1,474 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@c -A, --average report average posting amount
+
+To see the running total changed to a running average, use
+@option{-A}. The final posting's total will be the overall
+average of all displayed postings. The works in conjunction with
+period reporting, so that you can see your monthly average expenses
+with:
+
+@example
+ledger -AM reg ^expenses:food
+ledger -AMn reg ^expenses
+@end example
+
+This works in the balance report too:
+
+@example
+ledger -AM bal ^expenses:food
+ledger -AMs bal ^expenses
+@end example
+
+@c -D, --deviation report deviation from the average
+
+The @option{-D} option changes the running average into a deviation
+from the running average. This only makes sense in the register
+report, however.
+
+@example
+ledger -DM reg ^expenses:food
+@end example
+
+@c -%, --percentage report balance totals as a percentile of the parent
+
+In the balance report only, @option{-%} changes the reported totals
+into a percentage of the parent account. This kind of report is
+confusing if negative amounts are involved, and doesn't work at all if
+multiple commodities occur in an account's history. It has a somewhat
+limited usefulness, therefore, but in certain cases it can be handy,
+such as reviewing overall expenses:
+
+@example
+ledger -%s -S T bal ^expenses
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.109321</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/173.snapshots b/doc/Ledger.scriv/snapshots/173.snapshots
new file mode 100644
index 00000000..2a193242
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/173.snapshots
@@ -0,0 +1,446 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@c --totals in the "xml" report, include running total
+
+Normally in the @command{xml} report, only posting amounts are
+printed. To include the running total under a @samp{&lt;total&gt;} tag, use
+@option{--totals}. This does not affect any other report.
+
+@c -j, --amount-data print only raw amount data (useful for scripting)
+@c -J, --total-data print only raw total data
+
+In the register report only, the output can be changed with
+@option{-j} to show only the date and the amount---without
+commodities. This only makes sense if a single commodity appears in
+the report, but can be quite useful for scripting, or passing the data
+to Gnuplot. To show only the date and running total, use @option{-J}.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.11858499</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/174.snapshots b/doc/Ledger.scriv/snapshots/174.snapshots
new file mode 100644
index 00000000..b07439f3
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/174.snapshots
@@ -0,0 +1,446 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@c -d, --display EXPR display only postings matching EXPR
+
+With @option{-d} you can decide which postings (or accounts in the
+balance report) are displayed, according to a value expression. The
+computed total is not affected, only the display. This can be very
+useful for shortening a report without changing the running total:
+
+@example
+ledger -d 'd&gt;=[last month]' reg checking
+@end example
+
+This command shows the checking account's register, beginning from
+last month, but with the running total reflecting the entire history
+of the account.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.12788901</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/175.snapshots b/doc/Ledger.scriv/snapshots/175.snapshots
new file mode 100644
index 00000000..a0c17d1f
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/175.snapshots
@@ -0,0 +1,501 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@c -y, --date-format STR use STR as the date format (default: %Y/%m/%d)
+
+When dates are printed in any report, the default format is
+@samp{%Y/%m/%d}, which yields dates of the form @samp{YYYY/mm/dd}.
+This can be changed with @option{-y}, whose argument is a
+@code{strftime} string---see your system's C library documentation for
+the allowable codes. Mostly you will want to use @samp{%Y}, @samp{%m}
+and @samp{%d}, in whatever combination is convenient for your locale.
+
+@c -F, --format STR use STR as the format; for each report type, use:
+@c --balance-format --register-format --print-format
+@c --plot-amount-format --plot-total-format --equity-format
+@c --prices-format --wide-register-format
+
+To change the format of the entire reported line, use @option{-F}. It
+supports quite a large number of options, which are all documented in
+@ref{Format strings}. In addition, each specific kind of report
+(except for @command{xml}) can be changed using one of the following
+options:
+
+@table @option
+@item --balance-format
+@command{balance} report. Default:
+@smallexample
+%20T %2_%-a\n
+@end smallexample
+
+@item --register-format
+@command{register} report. Default:
+@smallexample
+%D %-.20P %-.22A %12.66t %12.80T\n%/%32|%-.22A %12.66t %12.80T\n
+@end smallexample
+
+@item --print-format
+@command{print} report. Default:
+@smallexample
+%D %-.35P %-.38A %22.108t %22.132T\n%/%48|%-.38A %22.108t %22.132T\n
+@end smallexample
+
+@item --plot-amount-format
+@command{register} report when @option{-j} (plot amount) is used. Default:
+@smallexample
+%D %(St)\n
+@end smallexample
+
+@item --plot-total-format
+@command{register} report when @option{-J} (plot total) is used. Default:
+@smallexample
+%D %(ST)\n
+@end smallexample
+
+@item --equity-format
+@command{equity} report. Default:
+@smallexample
+\n%D %Y%C%P\n %-34W %12o%n\n%/ %-34W %12o%n\n
+@end smallexample
+
+@item --prices-format
+@command{prices} report. Default:
+@smallexample
+\n%D %Y%C%P\n%/ %-34W %12t\n
+@end smallexample
+
+@item --wide-register-format
+@command{register} report when @option{-w} (wide) is used. Default:
+@smallexample
+%D %-.35P %-.38A %22.108t %22.132T\n%/%48|%-.38A %22.108t %22.132T\n
+@end smallexample
+@end table</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.13706899</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/176.snapshots b/doc/Ledger.scriv/snapshots/176.snapshots
new file mode 100644
index 00000000..2b234138
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/176.snapshots
@@ -0,0 +1,471 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>If your ledger file uses the standard top-level accounts: Assets,
+Liabilities, Income, Expenses, Equity: then the following queries will
+enable you to generate some typical accounting reports from your data.
+
+Your @emph{net worth} can be determined by balancing assets against
+liabilities:
+
+@example
+ledger bal ^assets ^liab
+@end example
+
+By removing long-term investment and loan accounts, you can see your
+current net liquidity (or liquid net worth):
+
+@example
+ledger bal ^assets ^liab -retirement -brokerage -loan
+@end example
+
+Balancing expenses against income yields your @emph{cash flow}, or net
+profit/loss:
+
+@example
+ledger bal ^exp ^inc
+@end example
+
+In this case, if the number is positive it means you spent more than
+you earned during the report period.
+
+@c ----------------------------------------------------------------------
+
+The most often used command is the ``balance'' command:
+
+@example
+export LEDGER=/home/johnw/doc/ledger.dat
+ledger balance
+@end example
+
+Here I've set my Ledger environment variable to point to where my
+ledger file is hiding. Thereafter, I needn't specify it again.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.146386</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/177.snapshots b/doc/Ledger.scriv/snapshots/177.snapshots
new file mode 100644
index 00000000..4592ddc1
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/177.snapshots
@@ -0,0 +1,463 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The balance command prints out the summarized balances of all my
+top-level accounts, excluding sub-accounts. In order to see the
+balances for a specific account, just specify a regular expression
+after the balance command:
+
+@example
+ledger balance expenses:food
+@end example
+
+This will show all the money that's been spent on food, since the
+beginning of the ledger. For food spending just this month
+(September), use:
+
+@example
+ledger -p sep balance expenses:food
+@end example
+
+Or maybe you want to see all of your assets, in which case the -s
+(show sub-accounts) option comes in handy:
+
+@example
+ledger -s balance ^assets
+@end example
+
+To exclude a particular account, use a regular expression with a
+leading minus sign. The following will show all expenses, but without
+food spending:
+
+@example
+ledger balance expenses -food
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.15574899</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/178.snapshots b/doc/Ledger.scriv/snapshots/178.snapshots
new file mode 100644
index 00000000..0d219775
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/178.snapshots
@@ -0,0 +1,434 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>There is no built-in way to report posting amounts or account
+balances in terms of percentages.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.16490701</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/18.snapshots b/doc/Ledger.scriv/snapshots/18.snapshots
new file mode 100644
index 00000000..84bc1109
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/18.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter Ledger in Practice</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.169599</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/180.snapshots b/doc/Ledger.scriv/snapshots/180.snapshots
new file mode 100644
index 00000000..aa9fab97
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/180.snapshots
@@ -0,0 +1,478 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Accountants will talk of ``credits'' and ``debits'', but the meaning
+is often different from the layman's understanding. To avoid
+confusion, Ledger uses only subtractions and additions, although the
+underlying intent is the same as standard accounting principles.
+
+Recall that every posting will involve two or more accounts.
+Money is transferred from one or more accounts to one or more other
+accounts. To record the posting, an amount is @emph{subtracted}
+from the source accounts, and @emph{added} to the target accounts.
+
+In order to write a Ledger transaction correctly, you must determine where
+the money comes from and where it goes to. For example, when you are
+paid a salary, you must add money to your bank account and also
+subtract it from an income account:
+
+@smallexample
+9/29 My Employer
+ Assets:Checking $500.00
+ Income:Salary $-500.00
+@end smallexample
+
+Why is the Income a negative figure? When you look at the balance
+totals for your ledger, you may be surprised to see that Expenses are
+a positive figure, and Income is a negative figure. It may take some
+getting used to, but to properly use a general ledger you must think
+in terms of how money moves. Rather than Ledger ``fixing'' the minus
+signs, let's understand why they are there.
+
+When you earn money, the money has to come from somewhere. Let's call
+that somewhere ``society''. In order for society to give you an
+income, you must take money away (withdraw) from society in order to
+put it into (make a payment to) your bank. When you then spend that
+money, it leaves your bank account (a withdrawal) and goes back to
+society (a payment). This is why Income will appear negative---it
+reflects the money you have drawn from society---and why Expenses will
+be positive---it is the amount you've given back. These additions and
+subtractions will always cancel each other out in the end, because you
+don't have the ability to create new money: it must always come from
+somewhere, and in the end must always leave. This is the beginning of
+economy, after which the explanation gets terribly difficult.
+
+Based on that explanation, here's another way to look at your balance
+report: every negative figure means that that account or person or
+place has less money now than when you started your ledger; and every
+positive figure means that that account or person or place has more
+money now that when you started your ledger. Make sense?</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.17864001</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/181.snapshots b/doc/Ledger.scriv/snapshots/181.snapshots
new file mode 100644
index 00000000..a3abd360
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/181.snapshots
@@ -0,0 +1,494 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Assets are money that you have, and Liabilities are money that you
+owe. ``Liabilities'' is just a more inclusive name for Debts.
+
+An Asset is typically increased by transferring money from an Income
+account, such as when you get paid. Here is a typical transaction:
+
+@smallexample
+2004/09/29 My Employer
+ Assets:Checking $500.00
+ Income:Salary
+@end smallexample
+
+Money, here, comes from an Income account belonging to ``My
+Employer'', and is transferred to your checking account. The money is
+now yours, which makes it an Asset.
+
+Liabilities track money owed to others. This can happen when you
+borrow money to buy something, or if you owe someone money. Here is
+an example of increasing a MasterCard liability by spending money with
+it:
+
+@smallexample
+2004/09/30 Restaurant
+ Expenses:Dining $25.00
+ Liabilities:MasterCard
+@end smallexample
+
+The Dining account balance now shows $25 spent on Dining, and a
+corresponding $25 owed on the MasterCard---and therefore shown as
+$-25.00. The MasterCard liability shows up as negative because it
+offsets the value of your assets.
+
+The combined total of your Assets and Liabilities is your net worth.
+So to see your current net worth, use this command:
+
+@example
+ledger balance ^assets ^liabilities
+@end example
+
+Relatedly, your Income accounts show up negative, because they
+transfer money @emph{from} an account in order to increase your
+assets. Your Expenses show up positive because that is where the
+money went to. The combined total of Income and Expenses is your cash
+flow. A positive cash flow means you are spending more than you make,
+since income is always a negative figure. To see your current cash
+flow, use this command:
+
+@example
+ledger balance ^income ^expenses
+@end example
+
+Another common question to ask of your expenses is: How much do I
+spend each month on X? Ledger provides a simple way of displaying
+monthly totals for any account. Here is an example that summarizes
+your monthly automobile expenses:
+
+@example
+ledger -M register expenses:auto
+@end example
+
+This assumes, of course, that you use account names like
+@samp{Expenses:Auto:Gas} and @samp{Expenses:Auto:Repair}.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.18805301</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/182.snapshots b/doc/Ledger.scriv/snapshots/182.snapshots
new file mode 100644
index 00000000..415188c4
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/182.snapshots
@@ -0,0 +1,578 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Sometimes you will want to spend money on behalf of someone else,
+which will eventually get repaid. Since the money is still ``yours'',
+it is really an asset. And since the expenditure was for someone
+else, you don't want it contaminating your Expenses reports. You will
+need to keep an account for tracking reimbursements.
+
+This is fairly easy to do in ledger. When spending the money, spend
+it @emph{to} your Assets:Reimbursements, using a different account for
+each person or business that you spend money for. For example:
+
+@smallexample
+2004/09/29 Circuit City
+ Assets:Reimbursements:Company XYZ $100.00
+ Liabilities:MasterCard
+@end smallexample
+
+This shows $100.00 spent on a MasterCard at Circuit City, with the
+expense was made on behalf of Company XYZ. Later, when Company XYZ
+pays the amount back, the money will transfer from that reimbursement
+account back to a regular asset account:
+
+@smallexample
+2004/09/29 Company XYZ
+ Assets:Checking $100.00
+ Assets:Reimbursements:Company XYZ
+@end smallexample
+
+This deposits the money owed from Company XYZ into a checking account,
+presumably because they paid the amount back with a check.
+
+But what to do if you run your own business, and you want to keep
+track of expenses made on your own behalf, while still tracking
+everything in a single ledger file? This is more complex, because you
+need to track two separate things: 1) The fact that the money should
+be reimbursed to you, and 2) What the expense account was, so that you
+can later determine where your company is spending its money.
+
+This kind of posting is best handled with mirrored postings in
+two different files, one for your personal accounts, and one for your
+company accounts. But keeping them in one file involves the same
+kinds of postings, so those are what is shown here. First, the
+personal transaction, which shows the need for reimbursement:
+
+@smallexample
+2004/09/29 Circuit City
+ Assets:Reimbursements:Company XYZ $100.00
+ Liabilities:MasterCard
+@end smallexample
+
+This is the same as above, except that you own Company XYZ, and are
+keeping track of its expenses in the same ledger file. This transaction
+should be immediately followed by an equivalent transaction, which shows the
+kind of expense, and also notes the fact that $100.00 is now payable
+to you:
+
+@smallexample
+2004/09/29 Circuit City
+ Company XYZ:Expenses:Computer:Software $100.00
+ Company XYZ:Accounts Payable:Your Name
+@end smallexample
+
+This second transaction shows that Company XYZ has just spent $100.00 on
+software, and that this $100.00 came from Your Name, which must be
+paid back.
+
+These two transactions can also be merged, to make things a little clearer.
+Note that all amounts must be specified now:
+
+@smallexample
+2004/09/29 Circuit City
+ Assets:Reimbursements:Company XYZ $100.00
+ Liabilities:MasterCard $-100.00
+ Company XYZ:Expenses:Computer:Software $100.00
+ Company XYZ:Accounts Payable:Your Name $-100.00
+@end smallexample
+
+To ``pay back'' the reimbursement, just reverse the order of
+everything, except this time drawing the money from a company asset,
+paying it to accounts payable, and then drawing it again from the
+reimbursement account, and paying it to your personal asset account.
+It's easier shown than said:
+
+@smallexample
+2004/10/15 Company XYZ
+ Assets:Checking $100.00
+ Assets:Reimbursements:Company XYZ $-100.00
+ Company XYZ:Accounts Payable:Your Name $100.00
+ Company XYZ:Assets:Checking $-100.00
+@end smallexample
+
+And now the reimbursements account is paid off, accounts payable is
+paid off, and $100.00 has been effectively transferred from the
+company's checking account to your personal checking account. The
+money simply ``waited''---in both @samp{Assets:Reimbursements:Company
+XYZ}, and @samp{Company XYZ:Accounts Payable:Your Name}---until such
+time as it could be paid off.
+
+The value of tracking expenses from both sides like that is that you
+do not contaminate your personal expense report with expenses made on
+behalf of others, while at the same time making it possible to
+generate accurate reports of your company's expenditures. It is more
+verbose than just paying for things with your personal assets, but it
+gives you a very accurate information trail.
+
+The advantage to keep these doubled transactions together is that they
+always stay in sync. The advantage to keeping them apart is that it
+clarifies the transfer's point of view. To keep the postings in
+separate files, just separate the two transactions that were joined above.
+For example, for both the expense and the pay-back shown above, the
+following four transactions would be created. Two in your personal ledger
+file:
+
+@smallexample
+2004/09/29 Circuit City
+ Assets:Reimbursements:Company XYZ $100.00
+ Liabilities:MasterCard $-100.00
+
+2004/10/15 Company XYZ
+ Assets:Checking $100.00
+ Assets:Reimbursements:Company XYZ $-100.00
+@end smallexample
+
+And two in your company ledger file:
+
+@smallexample
+!account Company XYZ
+
+2004/09/29 Circuit City
+ Expenses:Computer:Software $100.00
+ Accounts Payable:Your Name $-100.00
+
+2004/10/15 Company XYZ
+ Accounts Payable:Your Name $100.00
+ Assets:Checking $-100.00
+
+!end
+@end smallexample
+
+(Note: The @samp{!account} above means that all accounts mentioned in
+the file are children of that account. In this case it means that all
+activity in the file relates to Company XYZ).
+
+After creating these transactions, you will always know that $100.00 was
+spent using your MasterCard on behalf of Company XYZ, and that Company
+XYZ spent the money on computer software and paid it back about two
+weeks later.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.201664</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/183.snapshots b/doc/Ledger.scriv/snapshots/183.snapshots
new file mode 100644
index 00000000..0b3e5773
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/183.snapshots
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>A query such as the following shows all expenses since last
+October, sorted by total:
+
+@example
+ledger -b "last oct" -s -S T bal ^expenses
+@end example
+
+From left to right the options mean: Show transactions since October, 2003;
+show all sub-accounts; sort by the absolute value of the total; and
+report the balance for all expenses.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.211238</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/184.snapshots b/doc/Ledger.scriv/snapshots/184.snapshots
new file mode 100644
index 00000000..2973b709
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/184.snapshots
@@ -0,0 +1,471 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The following query makes it easy to see monthly expenses, with each
+month's expenses sorted by the amount:
+
+@example
+ledger -M --period-sort t reg ^expenses
+@end example
+
+Now, you might wonder where the money came from to pay for these
+things. To see that report, add @option{-r}, which shows the
+``related account'' postings:
+
+@example
+ledger -M --period-sort t -r reg ^expenses
+@end example
+
+But maybe this prints too much information. You might just want to
+see how much you're spending with your MasterCard. That kind of query
+requires the use of a display predicate, since the postings
+calculated must match @samp{^expenses}, while the postings
+displayed must match @samp{mastercard}. The command would be:
+
+@example
+ledger -M -r -d /mastercard/ reg ^expenses
+@end example
+
+This query says: Report monthly subtotals; report the ``related
+account'' postings; display only related postings whose
+account matches @samp{mastercard}, and base the calculation on
+postings matching @samp{^expenses}.
+
+This works just as well for report the overall total, too:
+
+@example
+ledger -s -r -d /mastercard/ reg ^expenses
+@end example
+
+The @option{-s} option subtotals all postings, just as @option{-M}
+subtotaled by the month. The running total in both cases is off,
+however, since a display expression is being used.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.220884</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/185.snapshots b/doc/Ledger.scriv/snapshots/185.snapshots
new file mode 100644
index 00000000..3791e6b3
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/185.snapshots
@@ -0,0 +1,457 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Here are some useful plots:
+
+@smallexample
+report -j -M reg ^expenses # monthly expenses
+report -J reg checking # checking account balance
+report -J reg ^income ^expenses # cash flow report
+
+# net worth report, ignoring non-$ postings
+
+report -J -l "Ua&gt;=@{\$0.01@}" reg ^assets ^liab
+
+# net worth report starting last February. the use of a display
+# predicate (-d) is needed, otherwise the balance will start at
+# zero, and thus the y-axis will not reflect the true balance
+
+report -J -l "Ua&gt;=@{\$0.01@}" -d "d&gt;=[last feb]" reg ^assets ^liab
+@end smallexample
+
+The last report uses both a calculation predicate (@option{-l}) and a
+display predicate (@option{-d}). The calculation predicates limits
+the report to postings whose amount is greater than $1 (which can
+only happen if the posting amount is in dollars). The display
+predicate limits the transactions @emph{displayed} to just those since last
+February, even those transactions from before then will be computed as part
+of the balance.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.24136901</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/186.snapshots b/doc/Ledger.scriv/snapshots/186.snapshots
new file mode 100644
index 00000000..67b92e34
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/186.snapshots
@@ -0,0 +1,450 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>If you have @command{Gnuplot} installed, you can graph any of the
+above register reports. The script to do this is included in the
+ledger distribution, and is named @file{scripts/report}. Install
+@file{report} anywhere along your @env{PATH}, and then use
+@command{report} instead of @command{ledger} when doing a register
+report. The only thing to keep in mind is that you must specify
+@option{-j} or @option{-J} to indicate whether Gnuplot should plot the
+amount, or the running total. For example, this command plots total
+monthly expenses made on your MasterCard.
+
+@example
+report -j -M -r -d /mastercard/ reg ^expenses
+@end example
+
+The @command{report} script is a very simple Bourne shell script, that
+passes a set of scripted commands to Gnuplot. Feel free to modify the
+script to your liking, since you may prefer histograms to line plots,
+for example.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.231296</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/188.snapshots b/doc/Ledger.scriv/snapshots/188.snapshots
new file mode 100644
index 00000000..b987c6bd
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/188.snapshots
@@ -0,0 +1,492 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Keeping a budget allows you to pay closer attention to your income and
+expenses, by reporting how far your actual financial activity is from
+your expectations.
+
+To start keeping a budget, put some period transactions at the top of your
+ledger file. A period transaction is almost identical to a regular transaction,
+except that it begins with a tilde and has a period expression in
+place of a payee. For example:
+
+@smallexample
+~ Monthly
+ Expenses:Rent $500.00
+ Expenses:Food $450.00
+ Expenses:Auto:Gas $120.00
+ Expenses:Insurance $150.00
+ Expenses:Phone $125.00
+ Expenses:Utilities $100.00
+ Expenses:Movies $50.00
+ Expenses $200.00 ; all other expenses
+ Assets
+
+~ Yearly
+ Expenses:Auto:Repair $500.00
+ Assets
+@end smallexample
+
+These two period transactions give the usual monthly expenses, as well as
+one typical yearly expense. For help on finding out what your average
+monthly expense is for any category, use a command like:
+
+@example
+ledger -p "this year" -MAs bal ^expenses
+@end example
+
+The reported totals are the current year's average for each account.
+
+Once these period transactions are defined, creating a budget report is as
+easy as adding @option{--budget} to the command-line. For example, a
+typical monthly expense report would be:
+
+@example
+ledger -M reg ^exp
+@end example
+
+To see the same report balanced against your budget, use:
+
+@example
+ledger --budget -M reg ^exp
+@end example
+
+A budget report includes only those accounts that appear in the
+budget. To see all expenses balanced against the budget, use
+@option{--add-budget}. You can even see only the unbudgeted expenses
+using @option{--unbudgeted}:
+
+@example
+ledger --unbudgeted -M reg ^exp
+@end example
+
+You can also use these flags with the @command{balance} command.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.255732</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/189.snapshots b/doc/Ledger.scriv/snapshots/189.snapshots
new file mode 100644
index 00000000..1471f4a2
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/189.snapshots
@@ -0,0 +1,451 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Sometimes it's useful to know what your finances will look like in the
+future, such as determining when an account will reach zero. Ledger
+makes this easy to do, using the same period transactions as are used for
+budgeting. An example forecast report can be generated with:
+
+@example
+ledger --forecast "T&gt;@{\$-500.00@}" register ^assets ^liabilities
+@end example
+
+This report continues outputting postings until the running total
+is greater than $-500.00. A final posting is always output, to
+show you what the total afterwards would be.
+
+Forecasting can also be used with the balance report, but by date
+only, and not against the running total:
+
+@example
+ledger --forecast "d&lt;[2010]" bal ^assets ^liabilities
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.26505899</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/19.snapshots b/doc/Ledger.scriv/snapshots/19.snapshots
new file mode 100644
index 00000000..c80e9e97
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/19.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter Random things</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.40400299</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/190.snapshots b/doc/Ledger.scriv/snapshots/190.snapshots
new file mode 100644
index 00000000..56763ae3
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/190.snapshots
@@ -0,0 +1,520 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Ledger makes no assumptions about the commodities you use; it only
+requires that you specify a commodity. The commodity may be any
+non-numeric string that does not contain a period, comma, forward
+slash or at-sign. It may appear before or after the amount, although
+it is assumed that symbols appearing before the amount refer to
+currencies, while non-joined symbols appearing after the amount refer
+to commodities. Here are some valid currency and commodity
+specifiers:
+
+@example
+$20.00 ; currency: twenty US dollars
+40 AAPL ; commodity: 40 shares of Apple stock
+60 DM ; currency: 60 Deutsch Mark
+£50 ; currency: 50 British pounds
+50 EUR ; currency: 50 Euros (or use appropriate symbol)
+@end example
+
+Ledger will examine the first use of any commodity to determine how
+that commodity should be printed on reports. It pays attention to
+whether the name of commodity was separated from the amount, whether
+it came before or after, the precision used in specifying the amount,
+whether thousand marks were used, etc. This is done so that printing
+the commodity looks the same as the way you use it.
+
+An account may contain multiple commodities, in which case it will
+have separate totals for each. For example, if your brokerage account
+contains both cash, gold, and several stock quantities, the balance
+might look like:
+
+@smallexample
+ $200.00
+100.00 AU
+ AAPL 40
+ BORL 100
+ FEQTX 50 Assets:Brokerage
+@end smallexample
+
+This balance report shows how much of each commodity is in your
+brokerage account.
+
+Sometimes, you will want to know the current street value of your
+balance, and not the commodity totals. For this to happen, you must
+specify what the current price is for each commodity. The price can
+be any commodity, in which case the balance will be computed in terms
+of that commodity. The usual way to specify prices is with a price
+history file, which might look like this:
+
+@smallexample
+P 2004/06/21 02:18:01 FEQTX $22.49
+P 2004/06/21 02:18:01 BORL $6.20
+P 2004/06/21 02:18:02 AAPL $32.91
+P 2004/06/21 02:18:02 AU $400.00
+@end smallexample
+
+Specify the price history to use with the @option{--price-db} option,
+with the @option{-V} option to report in terms of current market
+value:
+
+@example
+ledger --price-db prices.db -V balance brokerage
+@end example
+
+The balance for your brokerage account will be reported in US dollars,
+since the prices database uses that currency.
+
+@smallexample
+$40880.00 Assets:Brokerage
+@end smallexample
+
+You can convert from any commodity to any other commodity. Let's say
+you had $5000 in your checking account, and for whatever reason you
+wanted to know many ounces of gold that would buy, in terms of the
+current price of gold:
+
+@example
+ledger -T "@{1 AU@}*(O/P@{1 AU@})" balance checking
+@end example
+
+Although the total expression appears complex, it is simply saying
+that the reported total should be in multiples of AU units, where the
+quantity is the account total divided by the price of one AU. Without
+the initial multiplication, the reported total would still use the
+dollars commodity, since multiplying or dividing amounts always keeps
+the left value's commodity. The result of this command might be:
+
+@smallexample
+14.01 AU Assets:Checking
+@end smallexample</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.27479199</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/191.snapshots b/doc/Ledger.scriv/snapshots/191.snapshots
new file mode 100644
index 00000000..9dc97e23
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/191.snapshots
@@ -0,0 +1,450 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Whenever a commodity is purchased using a different commodity (such as
+a share of common stock using dollars), it establishes a price for
+that commodity on that day. It is also possible, by recording price
+details in a ledger file, to specify other prices for commodities at
+any given time. Such price transactions might look like those below:
+
+@smallexample
+P 2004/06/21 02:17:58 TWCUX $27.76
+P 2004/06/21 02:17:59 AGTHX $25.41
+P 2004/06/21 02:18:00 OPTFX $39.31
+P 2004/06/21 02:18:01 FEQTX $22.49
+P 2004/06/21 02:18:02 AAPL $32.91
+@end smallexample
+
+By default, ledger will not consider commodity prices when generating
+its various reports. It will always report balances in terms of the
+commodity total, rather than the current value of those commodities.
+To enable pricing reports, use one of the commodity reporting options.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.28429201</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/192.snapshots b/doc/Ledger.scriv/snapshots/192.snapshots
new file mode 100644
index 00000000..24992903
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/192.snapshots
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Sometimes a commodity has several forms which are all equivalent. An
+example of this is time. Whether tracked in terms of minutes, hours
+or days, it should be possible to convert between the various forms.
+Doing this requires the use of commodity equivalencies.
+
+For example, you might have the following two postings, one which
+transfers an hour of time into a @samp{Billable} account, and another
+which decreases the same account by ten minutes. The resulting report
+will indicate that fifty minutes remain:
+
+@smallexample
+2005/10/01 Work done for company
+ Billable:Client 1h
+ Project:XYZ
+
+2005/10/02 Return ten minutes to the project
+ Project:XYZ 10m
+ Billable:Client
+@end smallexample
+
+Reporting the balance for this ledger file produces:
+
+@smallexample
+ 50.0m Billable:Client
+ -50.0m Project:XYZ
+@end smallexample
+
+This example works because ledger already knows how to handle seconds,
+minutes and hours, as part of its time tracking support. Defining
+other equivalencies is simple. The following is an example that
+creates data equivalencies, helpful for tracking bytes, kilobytes,
+megabytes, and more:
+
+@smallexample
+C 1.00 Kb = 1024 b
+C 1.00 Mb = 1024 Kb
+C 1.00 Gb = 1024 Mb
+C 1.00 Tb = 1024 Gb
+@end smallexample
+
+Each of these definitions correlates a commodity (such as @samp{Kb})
+and a default precision, with a certain quantity of another commodity.
+In the above example, kilobytes are reporetd with two decimal places
+of precision and each kilobyte is equal to 1024 bytes.
+
+Equivalency chains can be as long as desired. Whenever a commodity
+would report as a decimal amount (less than @samp{1.00}), the next
+smallest commodity is used. If a commodity could be reported in terms
+of a higher commodity without resulting to a partial fraction, then
+the larger commodity is used.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.293807</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/193.snapshots b/doc/Ledger.scriv/snapshots/193.snapshots
new file mode 100644
index 00000000..73ce2d7e
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/193.snapshots
@@ -0,0 +1,466 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Since Ledger's accounts and commodity system is so flexible, you can
+have accounts that don't really exist, and use commodities that no one
+else recognizes. For example, let's say you are buying and selling
+various items in EverQuest, and want to keep track of them using a
+ledger. Just add items of whatever quantity you wish into your
+EverQuest account:
+
+@smallexample
+9/29 Get some stuff at the Inn
+ Places:Black's Tavern -3 Apples
+ Places:Black's Tavern -5 Steaks
+ EverQuest:Inventory
+@end smallexample
+
+Now your EverQuest:Inventory has 3 apples and 5 steaks in it. The
+amounts are negative, because you are taking @emph{from} Black's
+Tavern in order to add to your Inventory account. Note that you don't
+have to use @samp{Places:Black's Tavern} as the source account. You
+could use @samp{EverQuest:System} to represent the fact that you
+acquired them online. The only purpose for choosing one kind of
+source account over another is for generate more informative reports
+later on. The more you know, the better analysis you can perform.
+
+If you later sell some of these items to another player, the transaction
+would look like:
+
+@smallexample
+10/2 Sturm Brightblade
+ EverQuest:Inventory -2 Steaks
+ EverQuest:Inventory 15 Gold
+@end smallexample
+
+Now you've turned 2 steaks into 15 gold, courtesy of your customer,
+Sturm Brightblade.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.303377</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/194.snapshots b/doc/Ledger.scriv/snapshots/194.snapshots
new file mode 100644
index 00000000..610311bc
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/194.snapshots
@@ -0,0 +1,467 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The most confusing transaction in any ledger will be your equity account---
+because starting balances can't come out of nowhere.
+
+When you first start your ledger, you will likely already have money
+in some of your accounts. Let's say there's $100 in your checking
+account; then add a transaction to your ledger to reflect this amount.
+Where will money come from? The answer: your equity.
+
+@smallexample
+10/2 Opening Balance
+ Assets:Checking $100.00
+ Equity:Opening Balances
+@end smallexample
+
+But what is equity? You may have heard of equity when people talked
+about house mortgages, as ``the part of the house that you own''.
+Basically, equity is like the value of something. If you own a car
+worth $5000, then you have $5000 in equity in that car. In order to
+turn that car (a commodity) into a cash flow, or a credit to your bank
+account, you will have to debit the equity by selling it.
+
+When you start a ledger, you are probably already worth something.
+Your net worth is your current equity. By transferring the money in
+the ledger from your equity to your bank accounts, you are crediting
+the ledger account based on your prior equity. That is why, when you
+look at the balance report, you will see a large negative number for
+Equity that never changes: Because that is what you were worth (what
+you debited from yourself in order to start the ledger) before the
+money started moving around. If the total positive value of your
+assets is greater than the absolute value of your starting equity, it
+means you are making money.
+
+Clear as mud? Keep thinking about it. Until you figure it out, put
+@samp{-Equity} at the end of your balance command, to remove the
+confusing figure from the total.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.31266701</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/195.snapshots b/doc/Ledger.scriv/snapshots/195.snapshots
new file mode 100644
index 00000000..04848c8c
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/195.snapshots
@@ -0,0 +1,459 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Something that stops many people from keeping a ledger at all is the
+insanity of tracking small cash expenses. They rarely generate a
+receipt, and there are often a lot of small postings, rather than
+a few large ones, as with checks.
+
+One solution is: don't bother. Move your spending to a debit card,
+but in general ignore cash. Once you withdraw it from the ATM, mark
+it as already spent to an @samp{Expenses:Cash} category:
+
+@smallexample
+2004/03/15 ATM
+ Expenses:Cash $100.00
+ Assets:Checking
+@end smallexample
+
+If at some point you make a large cash expense that you want to track,
+just ``move'' the amount of the expense from @samp{Expenses:Cash} into
+the target account:
+
+@smallexample
+2004/03/20 Somebody
+ Expenses:Food $65.00
+ Expenses:Cash
+@end smallexample
+
+This way, you can still track large cash expenses, while ignoring all
+of the smaller ones.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.32201099</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/196.snapshots b/doc/Ledger.scriv/snapshots/196.snapshots
new file mode 100644
index 00000000..3ef5f828
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/196.snapshots
@@ -0,0 +1,564 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>There are situations when the accounts you're tracking are different
+between your clients and the financial institutions where money is
+kept. An example of this is working as the treasurer for a religious
+institution. From the secular point of view, you might be working
+with three different accounts:
+
+@itemize
+@item Checking
+@item Savings
+@item Credit Card
+@end itemize
+
+From a religious point of view, the community expects to divide its
+resources into multiple ``funds'', from which it makes purchases or
+reserves resources for later:
+
+@itemize
+@item School fund
+@item Building fund
+@item Community fund
+@end itemize
+
+The problem with this kind of setup is that when you spend money, it
+comes from two or more places at once: the account and the fund. And
+yet, the correlation of amounts between funds and accounts is rarely
+one-to-one. What if the school fund has @samp{$500.00}, but
+@samp{$400.00} of that comes from Checking, and @samp{$100.00} from
+Savings?
+
+Traditional finance packages require that the money reside in only one
+place. But there are really two ``views'' of the data: from the
+account point of view and from the fund point of view -- yet both sets
+should reflect the same overall expenses and cash flow. It's simply
+where the money resides that differs.
+
+This situation can be handled one of two ways. The first is using
+virtual postings to represent the fact that money is moving to and
+from two kind of accounts at the same time:
+
+@smallexample
+2004/03/20 Contributions
+ Assets:Checking $500.00
+ Income:Donations
+
+2004/03/25 Distribution of donations
+ [Funds:School] $300.00
+ [Funds:Building] $200.00
+ [Assets:Checking] $-500.00
+@end smallexample
+
+The use of square brackets in the second transaction ensures that the
+virtual postings balance to zero. Now money can be spent directly
+from a fund at the same time as money is drawn from a physical
+account:
+
+@smallexample
+2004/03/25 Payment for books (paid from Checking)
+ Expenses:Books $100.00
+ Assets:Checking $-100.00
+ (Funds:School) $-100.00
+@end smallexample
+
+When reports are generated, by default they'll appear in terms of the
+funds. In this case, you will likely want to mask out your
+@samp{Assets} account, because otherwise the balance won't make much
+sense:
+
+@example
+ledger bal -^Assets
+@end example
+
+If the @option{--real} option is used, the report will be in terms of
+the real accounts:
+
+@example
+ledger --real bal
+@end example
+
+If more asset accounts are needed as the source of a posting, just
+list them as you would normally, for example:
+
+@smallexample
+2004/03/25 Payment for books (paid from Checking)
+ Expenses:Books $100.00
+ Assets:Checking $-50.00
+ Liabilities:Credit Card $-50.00
+ (Funds:School) $-100.00
+@end smallexample
+
+The second way of tracking funds is to use transaction codes. In this
+respect the codes become like virtual accounts that embrace the entire
+set of postings. Basically, we are associating a transaction with a
+fund by setting its code. Here are two transactions that desposit money
+into, and spend money from, the @samp{Funds:School} fund:
+
+@smallexample
+2004/03/25 (Funds:School) Donations
+ Assets:Checking $100.00
+ Income:Donations
+
+2004/04/25 (Funds:School) Payment for books
+ Expenses:Books $50.00
+ Assets:Checking
+@end smallexample
+
+Note how the accounts now relate only to the real accounts, and any
+balance or registers reports will reflect this. That the transactions
+relate to a particular fund is kept only in the code.
+
+How does this become a fund report? By using the
+@option{--code-as-payee} option, you can generate a register report
+where the payee for each posting shows the code. Alone, this is
+not terribly interesting; but when combined with the
+@option{--by-payee} option, you will now see account subtotals for any
+postings related to a specific fund. So, to see the current
+monetary balances of all funds, the command would be:
+
+@smallexample
+ledger --code-as-payee -P reg ^Assets
+@end smallexample
+
+Or to see a particular funds expenses, the @samp{School} fund in this
+case:
+
+@smallexample
+ledger --code-as-payee -P reg ^Expenses -- School
+@end smallexample
+
+Both approaches yield different kinds of flexibility, depending on how
+you prefer to think of your funds: as virtual accounts, or as tags
+associated with particular transactions. Your own tastes will decide which
+is best for your situation.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.33141401</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/197.snapshots b/doc/Ledger.scriv/snapshots/197.snapshots
new file mode 100644
index 00000000..8375c8e5
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/197.snapshots
@@ -0,0 +1,488 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>After a while, your ledger can get to be pretty large. While this
+will not slow down the ledger program much---it's designed to process
+ledger files very quickly---things can start to feel ``messy''; and
+it's a universal complaint that when finances feel messy, people avoid
+them.
+
+Thus, archiving the data from previous years into their own files can
+offer a sense of completion, and freedom from the past. But how to
+best accomplish this with the ledger program? There are two commands
+that make it very simple: @command{print}, and @command{equity}.
+
+Let's take an example file, with data ranging from year 2000 until
+2004. We want to archive years 2000 and 2001 to their own file,
+leaving just 2003 and 2004 in the current file. So, use
+@command{print} to output all the earlier transactions to a file called
+@file{ledger-old.dat}:
+
+@smallexample
+ledger -f ledger.dat -b 2000 -e 2001 print &gt; ledger-old.dat
+@end smallexample
+
+To delete older data from the current ledger file, use @command{print}
+again, this time specifying year 2002 as the starting date:
+
+@example
+ledger -f ledger.dat -b 2002 print &gt; x
+mv x ledger.dat
+@end example
+
+However, now the current file contains @emph{only} postings from
+2002 onward, which will not yield accurate present-day balances,
+because the net income from previous years is no longer being tallied.
+To compensate for this, we must append an equity report for the old
+ledger at the beginning of the new one:
+
+@example
+ledger -f ledger-old.dat equity &gt; equity.dat
+cat equity.dat ledger.dat &gt; x
+mv x ledger.dat
+rm equity.dat
+@end example
+
+Now the balances reported from @file{ledger.dat} are identical to what
+they were before the data was split.
+
+How often should you split your ledger? You never need to, if you
+don't want to. Even eighty years of data will not slow down ledger
+much---and that's just using present day hardware! Or, you can keep
+the previous and current year in one file, and each year before that
+in its own file. It's really up to you, and how you want to organize
+your finances. For those who also keep an accurate paper trail, it
+might be useful to archive the older years to their own files, then
+burn those files to a CD to keep with the paper records---along with
+any electronic statements received during the year. In the arena of
+organization, just keep in mind this maxim: Do whatever keeps you
+doing it.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.34101999</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/198.snapshots b/doc/Ledger.scriv/snapshots/198.snapshots
new file mode 100644
index 00000000..cfd4c063
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/198.snapshots
@@ -0,0 +1,469 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>A virtual posting is when you, in your mind, see money as moving
+to a certain place, when in reality that money has not moved at all.
+There are several scenarios in which this type of tracking comes in
+handy, and each of them will be discussed in detail.
+
+To enter a virtual posting, surround the account name in
+parentheses. This form of usage does not need to balance. However,
+if you want to ensure the virtual posting balances with other
+virtual postings in the same transaction, use square brackets. For
+example:
+
+@smallexample
+10/2 Paycheck
+ Assets:Checking $1000.00
+ Income:Salary $-1000.00
+ (Debt:Alimony) $200.00
+@end smallexample
+
+In this example, after receiving a paycheck an alimony debt is
+increased---even though no money has moved around yet.
+
+@smallexample
+10/2 Paycheck
+ Assets:Checking $1000.00
+ Income:Salary $-1000.00
+ [Savings:Trip] $200.00
+ [Assets:Checking] $-200.00
+@end smallexample
+
+In this example, $200 has been deducted from checking toward savings
+for a trip. It will appear as though the money has been moved from
+the account into @samp{Savings:Trip}, although no money has actually
+moved anywhere.
+
+When balances are displayed, virtual postings will be factored in.
+To view balances without any virtual balances factored in, using the
+@option{-R} flag, for ``reality''.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.350416</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/199.snapshots b/doc/Ledger.scriv/snapshots/199.snapshots
new file mode 100644
index 00000000..ff0323dd
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/199.snapshots
@@ -0,0 +1,506 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>As a Bahá'í, I need to compute Huqúqu'lláh whenever I acquire assets.
+It is similar to tithing for Jews and Christians, or to Zakát for
+Muslims. The epost details of computing Huqúqu'lláh are somewhat
+complex, but if you have further interest, please consult the Web.
+
+Ledger makes this otherwise difficult law very easy. Just set up an
+automated posting at the top of your ledger file:
+
+@smallexample
+; This automated transaction will compute Huqúqu'lláh based on this
+; journal's postings. Any that match will affect the
+; Liabilities:Huququ'llah account by 19% of the value of that
+; posting.
+
+= /^(?:Income:|Expenses:(?:Business|Rent$|Furnishings|Taxes|Insurance))/
+ (Liabilities:Huququ'llah) 0.19
+@end smallexample
+
+This automated posting works by looking at each posting in the
+ledger file. If any match the given value expression, 19% of the
+posting's value is applied to the @samp{Liabilities:Huququ'llah}
+account. So, if $1000 is earned from @samp{Income:Salary}, $190 is
+added to @samp{Liabilities:Huqúqu'lláh}; if $1000 is spent on Rent,
+$190 is subtracted. The ultimate balance of Huqúqu'lláh reflects how
+much is owed in order to fulfill one's obligation to Huqúqu'lláh.
+When ready to pay, just write a check to cover the amount shown in
+@samp{Liabilities:Huququ'llah}. That transaction would look like:
+
+@smallexample
+2003/01/01 (101) Baha'i Huqúqu'lláh Trust
+ Liabilities:Huququ'llah $1,000.00
+ Assets:Checking
+@end smallexample
+
+That's it. To see how much Huqúq is currently owed based on your
+ledger transactions, use:
+
+@example
+ledger balance Liabilities:Huquq
+@end example
+
+This works fine, but omits one aspect of the law: that Huquq is only
+due once the liability exceeds the value of 19 mithqáls of gold (which
+is roughly 2.22 ounces). So what we want is for the liability to
+appear in the balance report only when it exceeds the present day
+value of 2.22 ounces of gold. This can be accomplished using the
+command:
+
+@smallexample
+ledger -Q -t "/Liab.*Huquq/?(a/P@{2.22 AU@}&lt;=@{-1.0@}&amp;a):a" -s bal liab
+@end smallexample
+
+With this command, the current price for gold is downloaded, and the
+Huqúqu'lláh is reported only if its value exceeds that of 2.22 ounces
+of gold. If you wish the liability to be reflected in the parent
+subtotal either way, use this instead:
+
+@smallexample
+ledger -Q -T "/Liab.*Huquq/?(O/P@{2.22 AU@}&lt;=@{-1.0@}&amp;O):O" -s bal liab
+@end smallexample
+
+In some cases, you may wish to refer to the account of whichever
+posting matched your automated transaction's value expression. To do
+this, use the special account name @samp{$account}:
+
+@smallexample
+= /^Some:Long:Account:Name/
+ [$account] -0.10
+ [Savings] 0.10
+@end smallexample
+
+This example causes 10% of the matching account's total to be deferred
+to the @samp{Savings} account---as a balanced virtual posting,
+which may be excluded from reports by using @option{--real}.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.35992801</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/20.snapshots b/doc/Ledger.scriv/snapshots/20.snapshots
new file mode 100644
index 00000000..1217e666
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/20.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter Anatomy of a journal file</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.41340101</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/200.snapshots b/doc/Ledger.scriv/snapshots/200.snapshots
new file mode 100644
index 00000000..352004f6
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/200.snapshots
@@ -0,0 +1,531 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>In the Ledger tarball is an Emacs module, @file{ledger.el}. This
+module makes the process of keeping a text ledger much easier for
+Emacs users. I recommend putting this at the top of your ledger file:
+
+@example
+; -*-ledger-*-
+@end example
+
+And this in your @file{.emacs} file, after copying @file{ledger.el} to
+your @file{site-lisp} directory:
+
+@example
+(load "ledger")
+@end example
+
+Now when you edit your ledger file, it will be in
+@command{ledger-mode}. @command{ledger-mode} adds these commands:
+
+@table @strong
+@item C-c C-a
+For quickly adding new transactions based on the form of older ones (see
+previous section).
+
+@item C-c C-c
+Toggles the ``cleared'' flag of the posting under point.
+
+@item C-c C-d
+Delete the transaction under point.
+
+@item C-c C-r
+Reconciles an account by displaying the postings in another
+buffer, where simply hitting the spacebar will toggle the pending flag
+of the posting in the ledger. Once all the appropriate
+postings have been marked, press C-c C-c in the reconcile buffer
+to ``commit'' the reconciliation, which will mark all of the transactions
+as cleared, and display the new cleared balance in the minibuffer.
+
+@item C-c C-m
+Set the default month for new transactions added with C-c C-a. This is
+handy if you have a large number of postings to enter from a
+previous month.
+
+@item C-c C-y
+Set the default year for new transactions added with C-c C-a. This is
+handy if you have a large number of postings to enter from a
+previous year.
+@end table
+
+Once you enter the reconcile buffer, there are several key commands
+available:
+
+@table @strong
+@item RET
+Visit the ledger file transaction corresponding to the reconcile transaction.
+
+@item C-c C-c
+Commit the reconcialation. This marks all of the marked postings
+as ``cleared'', saves the ledger file, and then displays the new
+cleared balance.
+
+@item C-l
+Refresh the reconcile buffer by re-reading postings from the
+ledger data file.
+
+@item SPC
+Toggle the posting under point as cleared.
+
+@item a
+Add a new transaction to the ledger data file, and refresh the reconcile
+buffer to include its postings (if the transaction is added to the same
+account as the one being reconciled).
+
+@item d
+Delete the transaction related to the posting under point. Note: This
+may result in multiple postings being deleted.
+
+@item n
+Move to the next line.
+
+@item p
+Move to the previous line.
+
+@item C-c C-r
+@item r
+Attempt to auto-reconcile the postings to the entered balance. If
+it can do so, it will mark all those postings as pending that
+would yield the specified balance.
+
+@item C-x C-s
+@item s
+Save the ledger data file, and show the current cleared balance for
+the account being reconciled.
+
+@item q
+Quit the reconcile buffer.
+@end table
+
+There is also an @command{emacs} command which can be used to output
+reports in a format directly @code{read}-able from Emacs Lisp.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.36992699</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/201.snapshots b/doc/Ledger.scriv/snapshots/201.snapshots
new file mode 100644
index 00000000..c6ffeb6a
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/201.snapshots
@@ -0,0 +1,445 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The Ledger tool is fast and simple, but it offers no custom method for
+actually editing the ledger. It assumes you know how to use a text
+editor, and like doing so. There is, at least, an Emacs mode that
+makes editing Ledger's data files much easier.
+
+You are also free to use GnuCash to maintain your ledger, and the
+Ledger program for querying and reporting on the contents of that
+ledger. It takes a little longer to parse the XML data format that
+GnuCash uses, but the end result is identical.
+
+Then again, why would anyone use a Gnome-centric, multi-megabyte
+behemoth to edit their data, and only a one megabyte binary to query
+it?</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.37944499</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/202.snapshots b/doc/Ledger.scriv/snapshots/202.snapshots
new file mode 100644
index 00000000..287c1219
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/202.snapshots
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The timeclock tool makes it easy to track time events, like clocking
+into and out of a particular job. These events accumulate in a
+timelog file.
+
+Each in/out event may have an optional description. If the ``in''
+description is a ledger account name, these in/out pairs may be viewed
+as virtual postings, adding time commodities (hours) to that
+account.
+
+For example, the command-line version of the timeclock tool could be
+used to begin a timelog file like:
+
+@example
+export TIMELOG=$HOME/.timelog
+ti ClientOne category
+sleep 10
+to waited for ten seconds
+@end example
+
+The @file{.timelog} file now contains:
+
+@smallexample
+i 2004/10/06 15:21:00 ClientOne category
+o 2004/10/06 15:21:10 waited for ten seconds
+@end smallexample
+
+Ledger parses this directly, as if it had seen the following transaction:
+
+@smallexample
+2004/10/06 category
+ (ClientOne) 10s
+@end smallexample
+
+In other words, the timelog event pair is seen as adding 0.00277h (ten
+seconds) worth of time to the @samp{ClientOne} account. This would be
+considered billable time, which later could be invoiced and credited
+to accounts receivable:
+
+@smallexample
+2004/11/01 (INV#1) ClientOne, Inc.
+ Receivable:ClientOne $0.10
+ ClientOne -0.00277h @@ $35.00
+@end smallexample
+
+The above posting converts the clocked time into an invoice for
+the time spent, at an hourly rate of $35. Once the invoice is paid,
+the money is deposited from the receivable account into a checking
+account:
+
+@smallexample
+2004/12/01 ClientOne, Inc.
+ Assets:Checking $0.10
+ Receivable:ClientOne
+@end smallexample
+
+And now the time spent has been turned into hard cash in the checking
+account.
+
+The advantage to using timeclock and invoicing to bill time is that
+you will always know, by looking at the balance report, epostly how
+much unbilled and unpaid time you've spent working for any particular
+client.
+
+I like to @samp{!include} my timelog at the top of my company's
+accounting ledger, with the attached prefix @samp{Billable}:
+
+@smallexample
+; -*-ledger-*-
+
+; This is the ledger file for my company. But first, include the
+; timelog data, entering all of the time events within the umbrella
+; account "Billable".
+
+!account Billable
+!include /home/johnw/.timelog
+!end
+
+; Here follows this fiscal year's postings for the company.
+
+2004/11/01 (INV#1) ClientOne, Inc.
+ Receivable:ClientOne $0.10
+ Billable:ClientOne -0.00277h @@ $35.00
+
+2004/12/01 ClientOne, Inc.
+ Assets:Checking $0.10
+ Receivable:ClientOne
+@end smallexample</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.388778</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/203.snapshots b/doc/Ledger.scriv/snapshots/203.snapshots
new file mode 100644
index 00000000..1cda4747
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/203.snapshots
@@ -0,0 +1,579 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>By default, Ledger uses a human-readable data format, and displays its
+reports in a manner meant to be read on screen. For the purpose of
+writing tools which use Ledger, however, it is possible to read and
+display data using XML. This section documents that format.
+
+The general format used for Ledger data is:
+
+@smallexample
+&lt;?xml version="1.0"?&gt;
+&lt;ledger&gt;
+ &lt;xact&gt;...&lt;/xact&gt;
+ &lt;xact&gt;...&lt;/xact&gt;
+ &lt;xact&gt;...&lt;/xact&gt;...
+&lt;/ledger&gt;
+@end smallexample
+
+The data stream is enclosed in a @samp{ledger} tag, which contains a
+series of one or more transactions. Each @samp{xact} describes the transaction
+and contains a series of one or more postings:
+
+@smallexample
+&lt;xact&gt;
+ &lt;en:date&gt;2004/03/01&lt;/en:date&gt;
+ &lt;en:cleared/&gt;
+ &lt;en:code&gt;100&lt;/en:code&gt;
+ &lt;en:payee&gt;John Wiegley&lt;/en:payee&gt;
+ &lt;en:postings&gt;
+ &lt;posting&gt;...&lt;/posting&gt;
+ &lt;posting&gt;...&lt;/posting&gt;
+ &lt;posting&gt;...&lt;/posting&gt;...
+ &lt;/en:postings&gt;
+&lt;/xact&gt;
+@end smallexample
+
+The date format for @samp{en:date} is always @samp{YYYY/MM/DD}. The
+@samp{en:cleared} tag is optional, and indicates whether the
+posting has been cleared or not. There is also an
+@samp{en:pending} tag, for marking pending postings. The
+@samp{en:code} and @samp{en:payee} tags both contain whatever text the
+user wishes.
+
+After the initial transaction data, there must follow a set of postings
+marked with @samp{en:postings}. Typically these postings will
+all balance each other, but if not they will be automatically balanced
+into an account named @samp{&lt;Unknown&gt;}.
+
+Within the @samp{en:postings} tag is a series of one or more
+@samp{posting}'s, which have the following form:
+
+@smallexample
+&lt;posting&gt;
+ &lt;tr:account&gt;Expenses:Computer:Hardware&lt;/tr:account&gt;
+ &lt;tr:amount&gt;
+ &lt;value type="amount"&gt;
+ &lt;amount&gt;
+ &lt;commodity flags="PT"&gt;$&lt;/commodity&gt;
+ &lt;quantity&gt;90.00&lt;/quantity&gt;
+ &lt;/amount&gt;
+ &lt;/value&gt;
+ &lt;/tr:amount&gt;
+&lt;/posting&gt;
+@end smallexample
+
+This is a basic posting. It may also be begin with
+@samp{tr:virtual} and/or @samp{tr:generated} tags, to indicate virtual
+and auto-generated postings. Then follows the @samp{tr:account}
+tag, which contains the full name of the account the posting is
+related to. Colons separate parent from child in an account name.
+
+Lastly follows the amount of the posting, indicated by
+@samp{tr:amount}. Within this tag is a @samp{value} tag, of which
+there are four different kinds, each with its own format:
+
+@enumerate
+@item boolean
+@item integer
+@item amount
+@item balance
+@end enumerate
+
+The format of a boolean value is @samp{true} or @samp{false}
+surrounded by a @samp{boolean} tag, for example:
+
+@smallexample
+&lt;boolean&gt;true&lt;/boolean&gt;
+@end smallexample
+
+The format of an integer value is the numerical value surrounded by an
+@samp{integer} tag, for example:
+
+@smallexample
+&lt;integer&gt;12036&lt;/integer&gt;
+@end smallexample
+
+The format of an amount contains two members, the commodity and the
+quantity. The commodity can have a set of flags that indicate how to
+display it. The meaning of the flags (all of which are optional) are:
+
+@table @strong
+@item P
+The commodity is prefixed to the value.
+@item S
+The commodity is separated from the value by a space.
+@item T
+Thousands markers are used to display the amount.
+@item E
+The format of the amount is European, with period used as a thousands
+marker, and comma used as the decimal point.
+@end table
+
+The actual quantity for an amount is an integer of arbitrary size.
+Ledger uses the GNU multi-precision math library to handle such
+values. The XML format assumes the reader to be equally capable.
+Here is an example amount:
+
+@smallexample
+&lt;value type="amount"&gt;
+ &lt;amount&gt;
+ &lt;commodity flags="PT"&gt;$&lt;/commodity&gt;
+ &lt;quantity&gt;90.00&lt;/quantity&gt;
+ &lt;/amount&gt;
+&lt;/value&gt;
+@end smallexample
+
+Lastly, a balance value contains a series of amounts, each with a
+different commodity. Unlike the name, such a value does need to
+balance. It is called a balance because it sums several amounts. For
+example:
+
+@smallexample
+&lt;value type="balance"&gt;
+ &lt;balance&gt;
+ &lt;amount&gt;
+ &lt;commodity flags="PT"&gt;$&lt;/commodity&gt;
+ &lt;quantity&gt;90.00&lt;/quantity&gt;
+ &lt;/amount&gt;
+ &lt;amount&gt;
+ &lt;commodity flags="TE"&gt;DM&lt;/commodity&gt;
+ &lt;quantity&gt;200.00&lt;/quantity&gt;
+ &lt;/amount&gt;
+ &lt;/balance&gt;
+&lt;/value&gt;
+@end smallexample
+
+That is the extent of the XML data format used by Ledger. It will
+output such data if the @command{xml} command is used, and can read
+the same data.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.39831501</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/204.snapshots b/doc/Ledger.scriv/snapshots/204.snapshots
new file mode 100644
index 00000000..9be3a4e7
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/204.snapshots
@@ -0,0 +1,468 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Whenever a commodity is exchanged for another in a posting, one of the
+two is considered @emph{primary}, and the other secondary.
+Primariness of a commodity is remembered, since the @option{--market}
+option only renders balances into secondary commodities, never
+primaries. To render primaries, use the @option{--exchange=COMMODITY}
+option.
+
+In all of the following examples, the P commodity is considered primary
+and the S is secondary (the P at the beginning of the line indicates a
+price-setting directive):
+
+@smallexample
+2009/01/01 Sample 1a
+ Assets:Brokerage:Stocks 100 S
+ Assets:Brokerage:Cash -100 P
+
+P 2009/01/15 00:00:00 S 2 P
+
+2009/02/01 Sample 2a
+ Assets:Brokerage:Stocks 100 S @ 1 P
+ Assets:Brokerage:Cash
+
+P 2009/02/01 00:00:00 S 4 P
+
+2009/03/01 Sample 3a
+ Assets:Brokerage:Stocks 100 S @@ 100 P
+ Assets:Brokerage:Cash
+
+P 2009/03/01 00:00:00 S 8 P
+
+2009/04/01 Sample 4a
+ Assets:Brokerage:Cash 100 P
+ Assets:Brokerage:Stocks -100 S @{1 P@}
+
+P 2009/04/01 00:00:00 S 16 P
+@end smallexample</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.40852299</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/205.snapshots b/doc/Ledger.scriv/snapshots/205.snapshots
new file mode 100644
index 00000000..bd7510dd
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/205.snapshots
@@ -0,0 +1,466 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Everything begins with a journal file---the anatomy of which is covered
+in detail in chapter one. To review: a @emph{journal} contains one or
+more @emph{transactions}, each of which refers to two or more
+@emph{postings}. A @emph{posting} specifies that a given
+@emph{amount} is added to, or subtracted from, an @emph{account}.
+(@emph{Accounts} may be nested hierarchically by separating the elements
+using a colon). Lastly, an @emph{amount} is a figure representing a
+given @emph{quantity} of a @emph{commodity}. Here follows a review of
+these terms, which are all used extensively throughout this chapter:
+
+@table @emph
+@item journal
+A journal is a data file containing a series of transactions.
+
+@item transaction
+a transaction relates a group of two or more postings, with the absolute
+constraint that the total sum of a transaction's postings must equal
+zero. That is, every transaction in a journal must @emph{balance} to zero.
+
+@item posting
+Postings record how commodities are moved between accounts. If you
+spent money on a movie ticket, for example, such a transaction would have two
+postings: One to show how the money was taken from your wallet, and
+another to show how it was applied to your movie expenses.
+
+@item account
+An account
+
+@item amount
+
+@item quantity
+
+@item commodity
+@end table</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.41803801</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/207.snapshots b/doc/Ledger.scriv/snapshots/207.snapshots
new file mode 100644
index 00000000..dd2c4ca4
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/207.snapshots
@@ -0,0 +1,445 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Once you have a journal file representing a recent history of your
+finances, the next step is to generate reports in order to give richer
+meaning to this data. For example: Where do you spend your money? Do
+you have enough to cover upcoming expenses? Are you creating or losing
+net worth? Are your investment performing well? All of these questions
+can be answered easily with Ledger---if you know how to ask them.
+
+Preparing complex reports is not a simple task, but neither is it a
+difficult one. All that's required is a proper understanding of how
+Ledger views your data, and how it prepares it for reporting.
+
+After Ledger reads a journal file, it creates an in-memory
+representation reflecting the order and composition of those transactions.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.43257499</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/21.snapshots b/doc/Ledger.scriv/snapshots/21.snapshots
new file mode 100644
index 00000000..7bdccf85
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/21.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter Example accounting practices</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.42269701</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/211.snapshots b/doc/Ledger.scriv/snapshots/211.snapshots
new file mode 100644
index 00000000..f16e557e
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/211.snapshots
@@ -0,0 +1,456 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The following sections discuss how Ledger is architected, from the
+ground up, and will show how to use the various parts of the Ledger
+library from your own scripts. Ledger essentially follows five steps in
+reporting data to the user:
+
+@enumerate
+@item Parse journal file into an internal representation
+@item Perform any implied math within the journal file
+@item ``Face'' this internal representation as a virtual document
+@item Apply a series of transforms to the virtual document
+@item Display the virtual document using a formatting command
+@end enumerate
+
+The calculations in step two are specified by the user, such as when a
+posting's value might contain mathematical operators. The
+calculations in step four are implied in the transformations, for
+example when the @option{--average} option is used.
+
+At the core, however, Ledger is basically a sophisticated calculator
+with special knowledge about commoditized values. It knows what you
+mean if you add ten dollars to twenty euros, and later ask for the
+balance of that particular account. So it follows that first we must
+discuss how Ledger deals with math, and from there move on to describing
+how the steps above are achieved.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.45634499</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/213.snapshots b/doc/Ledger.scriv/snapshots/213.snapshots
new file mode 100644
index 00000000..58cfdbc3
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/213.snapshots
@@ -0,0 +1,449 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The most fundamental type in Ledger is the amount, which may or may
+not have a commodity attached to it. First, we'll deal with the bare
+case, just to show how the amount type works. In C++, most all of
+Ledger's internal types end in @code{_t}; in Python, the same type
+name is used, but the @code{_t} suffix is dropped. Examples of usage
+in both languages will be presented throughout.
+
+amount_t
+commodity_t
+updater_t
+datetime_t
+balance_t
+balance_pair_t
+value_t
+valexpr_t
+format_t
+mask_t</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.47044501</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/214.snapshots b/doc/Ledger.scriv/snapshots/214.snapshots
new file mode 100644
index 00000000..78280df9
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/214.snapshots
@@ -0,0 +1,437 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>journal_t
+account_t
+xact_t
+post_t
+parser_t</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.479931</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/218.snapshots b/doc/Ledger.scriv/snapshots/218.snapshots
new file mode 100644
index 00000000..378e5db0
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/218.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@bye</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.49920401</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/22.snapshots b/doc/Ledger.scriv/snapshots/22.snapshots
new file mode 100644
index 00000000..e3b6b288
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/22.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter Generating useful reports</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.42793199</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/23.snapshots b/doc/Ledger.scriv/snapshots/23.snapshots
new file mode 100644
index 00000000..98e8dfdc
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/23.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter Value expressions</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.43738899</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/24.snapshots b/doc/Ledger.scriv/snapshots/24.snapshots
new file mode 100644
index 00000000..2507d1ef
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/24.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter Format strings</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.442112</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/25.snapshots b/doc/Ledger.scriv/snapshots/25.snapshots
new file mode 100644
index 00000000..9ee68e55
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/25.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter Extensions in Python</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.44688401</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/26.snapshots b/doc/Ledger.scriv/snapshots/26.snapshots
new file mode 100644
index 00000000..c6e1a043
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/26.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter The design of Ledger</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.451664</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/28.snapshots b/doc/Ledger.scriv/snapshots/28.snapshots
new file mode 100644
index 00000000..731596f7
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/28.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Commands</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.70983401</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/29.snapshots b/doc/Ledger.scriv/snapshots/29.snapshots
new file mode 100644
index 00000000..96b3dfa6
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/29.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Options</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.79829299</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/30.snapshots b/doc/Ledger.scriv/snapshots/30.snapshots
new file mode 100644
index 00000000..99a61e93
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/30.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Period expressions</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.85450101</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/31.snapshots b/doc/Ledger.scriv/snapshots/31.snapshots
new file mode 100644
index 00000000..e77d8a56
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/31.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Format strings</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.86376899</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/32.snapshots b/doc/Ledger.scriv/snapshots/32.snapshots
new file mode 100644
index 00000000..a20430db
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/32.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Value expressions</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.87319401</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/33.snapshots b/doc/Ledger.scriv/snapshots/33.snapshots
new file mode 100644
index 00000000..4554c58b
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/33.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section File format</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.93844599</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/4.snapshots b/doc/Ledger.scriv/snapshots/4.snapshots
new file mode 100644
index 00000000..345865fd
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/4.snapshots
@@ -0,0 +1,438 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>\input texinfo @c -*-texinfo-*-
+
+@setfilename ledger.info
+@settitle Ledger: Command-Line Accounting
+
+@dircategory User Applications</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.652343</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/44.snapshots b/doc/Ledger.scriv/snapshots/44.snapshots
new file mode 100644
index 00000000..51f9c67b
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/44.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection balance</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.71448901</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/5.snapshots b/doc/Ledger.scriv/snapshots/5.snapshots
new file mode 100644
index 00000000..de8b5dfc
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/5.snapshots
@@ -0,0 +1,490 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@copying
+Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ 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.
+@end copying
+
+@documentencoding utf-8
+
+@iftex
+@finalout
+@end iftex
+
+@titlepage
+@title Ledger: Command-Line Accounting
+@author John Wiegley
+@end titlepage
+
+@direntry
+* Ledger: (ledger). Command Line Accounting
+@end direntry
+
+@contents
+
+@ifnottex
+@top Overview
+
+@insertcopying
+@end ifnottex
+
+@ifnottex
+@section Copyright
+@insertcopying
+@end ifnottex</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.65798301</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/54.snapshots b/doc/Ledger.scriv/snapshots/54.snapshots
new file mode 100644
index 00000000..1791b314
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/54.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection register</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.72422901</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/55.snapshots b/doc/Ledger.scriv/snapshots/55.snapshots
new file mode 100644
index 00000000..b347b511
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/55.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection print</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.73339599</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/56.snapshots b/doc/Ledger.scriv/snapshots/56.snapshots
new file mode 100644
index 00000000..8c64c1ea
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/56.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection output</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.74269</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/57.snapshots b/doc/Ledger.scriv/snapshots/57.snapshots
new file mode 100644
index 00000000..81aa04e9
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/57.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection xml</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.75199699</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/58.snapshots b/doc/Ledger.scriv/snapshots/58.snapshots
new file mode 100644
index 00000000..03e71e31
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/58.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection emacs</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.761289</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/59.snapshots b/doc/Ledger.scriv/snapshots/59.snapshots
new file mode 100644
index 00000000..0bf4d0cc
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/59.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection equity</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.77038899</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/6.snapshots b/doc/Ledger.scriv/snapshots/6.snapshots
new file mode 100644
index 00000000..316a90b2
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/6.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@chapter Introduction</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.662736</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/60.snapshots b/doc/Ledger.scriv/snapshots/60.snapshots
new file mode 100644
index 00000000..ce365004
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/60.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection prices</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.77979299</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/61.snapshots b/doc/Ledger.scriv/snapshots/61.snapshots
new file mode 100644
index 00000000..d95a6c48
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/61.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection xact</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.78911</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/62.snapshots b/doc/Ledger.scriv/snapshots/62.snapshots
new file mode 100644
index 00000000..391fe463
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/62.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Basic options</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.80758899</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/63.snapshots b/doc/Ledger.scriv/snapshots/63.snapshots
new file mode 100644
index 00000000..7b793b68
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/63.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Report filtering</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.816717</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/64.snapshots b/doc/Ledger.scriv/snapshots/64.snapshots
new file mode 100644
index 00000000..49b08222
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/64.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Output customization</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.82597801</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/65.snapshots b/doc/Ledger.scriv/snapshots/65.snapshots
new file mode 100644
index 00000000..94c12964
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/65.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Commodity reporting</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.835522</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/66.snapshots b/doc/Ledger.scriv/snapshots/66.snapshots
new file mode 100644
index 00000000..6e2a7996
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/66.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Environment variables</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.84474701</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/67.snapshots b/doc/Ledger.scriv/snapshots/67.snapshots
new file mode 100644
index 00000000..6658fb07
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/67.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Variables</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.88238201</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/69.snapshots b/doc/Ledger.scriv/snapshots/69.snapshots
new file mode 100644
index 00000000..05cbcfab
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/69.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Functions</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.91026899</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/7.snapshots b/doc/Ledger.scriv/snapshots/7.snapshots
new file mode 100644
index 00000000..3caecc9b
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/7.snapshots
@@ -0,0 +1,552 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>Ledger is an accounting tool with the moxie to exist. It provides no
+bells or whistles, and returns the user to the days before user
+interfaces were even a twinkling in their father's CRT.
+
+What it does offer is a double-entry accounting ledger with all the
+flexibility and muscle of its modern day cousins, without any of the
+fat. Think of it as the Bran Muffin of accounting tools.
+
+To use it, you need to start keeping a ledger. This is the basis of
+all accounting, and if you haven't started yet, now is the time to
+learn. The little booklet that comes with your checkbook is a ledger,
+so we'll describe double-entry accounting in terms of that.
+
+A checkbook ledger records debits (subtractions, or withdrawals) and
+credits (additions, or deposits) with reference to a single account:
+the checking account. Where the money comes from, and where it goes
+to, are described in the payee field, where you write the person or
+company's name. The ultimate aim of keeping a checkbook ledger is to
+know how much money is available to spend. That's really the aim of
+all ledgers.
+
+What computers add is the ability to walk through these postings,
+and tell you things about your spending habits; to let you devise
+budgets and get control over your spending; to squirrel away money
+into virtual savings account without having to physically move money
+around; etc. As you keep your ledger, you are recording information
+about your life and habits, and sometimes that information can start
+telling you things you aren't aware of. Such is the aim of all good
+accounting tools.
+
+The next step up from a checkbook ledger, is a ledger that keeps track
+of all your accounts, not just checking. In such a ledger, you record
+not only who gets paid---in the case of a debit---but where the money
+came from. In a checkbook ledger, its assumed that all the money
+comes from your checking account. But in a general ledger, you write
+posting two-lines: the source account and target account.
+@emph{There must always be a debit from at least one account for every
+credit made to another account}. This is what is meant by
+``double-entry'' accounting: the ledger must always balance to zero,
+with an equal number of debits and credits.
+
+For example, let's say you have a checking account and a brokerage
+account, and you can write checks from both of them. Rather than keep
+two checkbooks, you decide to use one ledger for both. In this
+general ledger you need to record a payment to Pacific Bell for your
+monthly phone bill. The cost is $23.00, let's say, and you want to
+pay it from your checking account. In the general ledger you need to
+say where the money came from, in addition to where it's going to.
+The transaction might look like this:
+
+@smallexample
+9/29 BAL Pacific Bell $-200.00 $-200.00
+ Equity:Opening Balances $200.00
+9/29 BAL Checking $100.00 $100.00
+ Equity:Opening Balances $-100.00
+9/29 100 Pacific Bell $23.00 $223.00
+ Checking $-23.00 $77.00
+@end smallexample
+
+The first line shows a payment to Pacific Bell for $23.00. Because
+there is no ``balance'' in a general ledger---it's always zero---we
+write in the total balance of all payments to ``Pacific Bell'', which
+now is $223.00 (previously the balance was $200.00). This is done by
+looking at the last transaction for ``Pacific Bell'' in the ledger, adding
+$23.00 to that amount, and writing the total in the balance column.
+And the money came from ``Checking''---a withdrawal of $23.00---which
+leaves the ending balance in ``Checking'' at $77.00. This is a very
+manual procedure; but that's where computers come in...
+
+The posting must balance to $0: $23 went to Pacific Bell, $23 came
+from Checking. There is nothing left over to be accounted for, since
+the money has simply moved from one account to another. This is the
+basis of double-entry accounting: that money never pops in or out of
+existence; it is always a posting from one account to another.
+
+Keeping a general ledger is the same as keeping two separate ledgers:
+One for Pacific Bell and one for Checking. In that case, each time a
+payment is written into one, you write a corresponding withdrawal into
+the other. This makes it easier to write in a ``running balance'',
+since you don't have to look back at the last time the account was
+referenced---but it also means having a lot of ledger books, if you
+deal with multiple accounts.
+
+Enter the beauty of computerized accounting. The purpose of the
+Ledger program is to make general ledger accounting simple, by keeping
+track of the balances for you. Your only job is to enter the
+postings. If a posting does not balance, Ledger displays an
+error and indicates the incorrect posting.@footnote{In some
+special cases, it automatically balances this transaction for you.}
+
+In summary, there are two aspects of Ledger use: updating the ledger
+data file, and using the Ledger tool to view the summarized result of
+your transactions.
+
+And just for the sake of example---as a starting point for those who
+want to dive in head-first---here are the ledger transactions from above,
+formatting as the ledger program wishes to see them:
+
+@smallexample
+2004/09/29 Pacific Bell
+ Payable:Pacific Bell $-200.00
+ Equity:Opening Balances
+
+2004/09/29 Checking
+ Accounts:Checking $100.00
+ Equity:Opening Balances
+
+2004/09/29 Pacific Bell
+ Payable:Pacific Bell $23.00
+ Accounts:Checking
+@end smallexample
+
+The account balances and registers in this file, if saved as
+@file{ledger.dat}, could be reported using:
+
+@example
+$ ledger -f ledger.dat balance
+$ ledger -f ledger.dat register checking
+$ ledger -f ledger.dat register bell
+@end example</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.667629</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/70.snapshots b/doc/Ledger.scriv/snapshots/70.snapshots
new file mode 100644
index 00000000..09db4a94
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/70.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Operators</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.91948199</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/71.snapshots b/doc/Ledger.scriv/snapshots/71.snapshots
new file mode 100644
index 00000000..3aaf80bb
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/71.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Complex expressions</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.92894399</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/72.snapshots b/doc/Ledger.scriv/snapshots/72.snapshots
new file mode 100644
index 00000000..d010644d
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/72.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsubsection Posting/account details</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.891738</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/73.snapshots b/doc/Ledger.scriv/snapshots/73.snapshots
new file mode 100644
index 00000000..9bbd584b
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/73.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsubsection Calculated totals</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.901106</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/74.snapshots b/doc/Ledger.scriv/snapshots/74.snapshots
new file mode 100644
index 00000000..4ec469ee
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/74.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Checking balances</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.957746</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/75.snapshots b/doc/Ledger.scriv/snapshots/75.snapshots
new file mode 100644
index 00000000..80a5b4ff
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/75.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section The register report</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.98629501</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/76.snapshots b/doc/Ledger.scriv/snapshots/76.snapshots
new file mode 100644
index 00000000..568e1f58
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/76.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Selecting postings</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.00501299</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/77.snapshots b/doc/Ledger.scriv/snapshots/77.snapshots
new file mode 100644
index 00000000..221f5cea
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/77.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Massaging register output</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.067801</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/78.snapshots b/doc/Ledger.scriv/snapshots/78.snapshots
new file mode 100644
index 00000000..7bd69598
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/78.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Standard queries</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.14189199</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/79.snapshots b/doc/Ledger.scriv/snapshots/79.snapshots
new file mode 100644
index 00000000..a1e3224d
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/79.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Reporting balance totals</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.15111801</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/8.snapshots b/doc/Ledger.scriv/snapshots/8.snapshots
new file mode 100644
index 00000000..1d6f91d7
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/8.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section More introduction</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.67256701</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/80.snapshots b/doc/Ledger.scriv/snapshots/80.snapshots
new file mode 100644
index 00000000..8a90dfcb
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/80.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Reporting percentages</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.16041401</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/81.snapshots b/doc/Ledger.scriv/snapshots/81.snapshots
new file mode 100644
index 00000000..6d8d5eee
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/81.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Sub-account balances</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.96709001</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/82.snapshots b/doc/Ledger.scriv/snapshots/82.snapshots
new file mode 100644
index 00000000..1af61824
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/82.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Specific account balances</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.976567</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/83.snapshots b/doc/Ledger.scriv/snapshots/83.snapshots
new file mode 100644
index 00000000..daed41d8
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/83.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Specific register queries</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.99571201</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/84.snapshots b/doc/Ledger.scriv/snapshots/84.snapshots
new file mode 100644
index 00000000..c5da21a3
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/84.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection By date</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.014238</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/85.snapshots b/doc/Ledger.scriv/snapshots/85.snapshots
new file mode 100644
index 00000000..27307502
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/85.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection By status</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.023626</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/86.snapshots b/doc/Ledger.scriv/snapshots/86.snapshots
new file mode 100644
index 00000000..3d2beb4f
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/86.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection By relationship</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.03355399</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/87.snapshots b/doc/Ledger.scriv/snapshots/87.snapshots
new file mode 100644
index 00000000..8ff59806
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/87.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection By budget</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.042889</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/88.snapshots b/doc/Ledger.scriv/snapshots/88.snapshots
new file mode 100644
index 00000000..f5753895
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/88.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection By value expression</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.05867699</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/89.snapshots b/doc/Ledger.scriv/snapshots/89.snapshots
new file mode 100644
index 00000000..fe14aa11
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/89.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Summarizing</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.07697701</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/9.snapshots b/doc/Ledger.scriv/snapshots/9.snapshots
new file mode 100644
index 00000000..a89e7880
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/9.snapshots
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>The most important part of accounting is keeping a good ledger. If
+you have a good ledger, tools can be written to work whatever
+mathematically tricks you need to better understand your spending
+patterns. Without a good ledger, no tool, however smart, can help
+you.
+
+The Ledger program aims at making ledger transaction as simple as possible.
+Since it is a command-line tool, it does not provide a user interface
+for keeping a ledger. If you like, you may use GnuCash to maintain
+your ledger, in which case the Ledger program will read GnuCash's data
+files directly. In that case, read the GnuCash manual now, and skip
+to the next chapter.
+
+If you are not using GnuCash, but a text editor to maintain your
+ledger, read on. Ledger has been designed to make data transaction as
+simple as possible, by keeping the ledger format easy, and also by
+automagically determining as much information as possible based on the
+nature of your transactions.
+
+For example, you do not need to tell Ledger about the accounts you
+use. Any time Ledger sees a posting involving an account it knows
+nothing about, it will create it. If you use a commodity that is new
+to Ledger, it will create that commodity, and determine its display
+characteristics (placement of the symbol before or after the amount,
+display precision, etc) based on how you used the commodity in the
+posting.
+
+Here is the Pacific Bell example from above, given as a Ledger
+posting:
+
+@smallexample
+9/29 (100) Pacific Bell
+ Expenses:Utilities:Phone $23.00
+ Assets:Checking $-23.00
+@end smallexample
+
+As you can see, it is very similar to what would be written on paper,
+minus the computed balance totals, and adding in account names that
+work better with Ledger's scheme of things. In fact, since Ledger is
+smart about many things, you don't need to specify the balanced
+amount, if it is the same as the first line:
+
+@smallexample
+9/29 (100) Pacific Bell
+ Expenses:Utilities:Phone $23.00
+ Assets:Checking
+@end smallexample
+
+For this transaction, Ledger will figure out that $-23.00 must come from
+@samp{Assets:Checking} in order to balance the transaction.</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380388.67717099</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/90.snapshots b/doc/Ledger.scriv/snapshots/90.snapshots
new file mode 100644
index 00000000..b6e072d8
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/90.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Quick periods</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.08627999</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/91.snapshots b/doc/Ledger.scriv/snapshots/91.snapshots
new file mode 100644
index 00000000..7c11c176
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/91.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Ordering and width</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.095442</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/92.snapshots b/doc/Ledger.scriv/snapshots/92.snapshots
new file mode 100644
index 00000000..947a7ced
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/92.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Averages and percentages</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.10484099</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/93.snapshots b/doc/Ledger.scriv/snapshots/93.snapshots
new file mode 100644
index 00000000..6abbb2b6
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/93.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Reporting total data</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.114095</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/94.snapshots b/doc/Ledger.scriv/snapshots/94.snapshots
new file mode 100644
index 00000000..99b42ff8
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/94.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Display by value expression</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.12321699</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/95.snapshots b/doc/Ledger.scriv/snapshots/95.snapshots
new file mode 100644
index 00000000..59e8b0dc
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/95.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Change report format</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.13254401</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/96.snapshots b/doc/Ledger.scriv/snapshots/96.snapshots
new file mode 100644
index 00000000..a013f082
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/96.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Stating where money goes</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.174151</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/97.snapshots b/doc/Ledger.scriv/snapshots/97.snapshots
new file mode 100644
index 00000000..870db8d6
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/97.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Assets and Liabilities</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.183505</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/98.snapshots b/doc/Ledger.scriv/snapshots/98.snapshots
new file mode 100644
index 00000000..40760200
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/98.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@subsection Tracking reimbursable expenses</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.19689199</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/snapshots/99.snapshots b/doc/Ledger.scriv/snapshots/99.snapshots
new file mode 100644
index 00000000..c4910e9c
--- /dev/null
+++ b/doc/Ledger.scriv/snapshots/99.snapshots
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>$archiver</key>
+ <string>NSKeyedArchiver</string>
+ <key>$objects</key>
+ <array>
+ <string>$null</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>37</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>2</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>4</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>5</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>6</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>7</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>35</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>Title</string>
+ <string>Text</string>
+ <string>Date</string>
+ <string>Untitled Snapshot</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>34</integer>
+ </dict>
+ <key>NSAttributes</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>10</integer>
+ </dict>
+ <key>NSDelegate</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>0</integer>
+ </dict>
+ <key>NSString</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>9</integer>
+ </dict>
+ <key>NS.string</key>
+ <string>@section Typical queries</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableString</string>
+ <string>NSString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableString</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>33</integer>
+ </dict>
+ <key>NS.keys</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>11</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>12</integer>
+ </dict>
+ </array>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>13</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>30</integer>
+ </dict>
+ </array>
+ </dict>
+ <string>NSParagraphStyle</string>
+ <string>NSFont</string>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>29</integer>
+ </dict>
+ <key>NSAlignment</key>
+ <integer>4</integer>
+ <key>NSLineHeightMultiple</key>
+ <real>1.1000000238418579</real>
+ <key>NSTabStops</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>14</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>28</integer>
+ </dict>
+ <key>NS.objects</key>
+ <array>
+ <dict>
+ <key>CF$UID</key>
+ <integer>15</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>17</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>18</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>19</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>20</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>21</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>22</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>23</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>24</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>25</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>26</integer>
+ </dict>
+ <dict>
+ <key>CF$UID</key>
+ <integer>27</integer>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>28</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSTextTab</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSTextTab</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>56</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>84</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>112</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>140</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>168</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>196</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>224</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>252</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>280</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>308</real>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>16</integer>
+ </dict>
+ <key>NSLocation</key>
+ <real>336</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSArray</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSParagraphStyle</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSParagraphStyle</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>32</integer>
+ </dict>
+ <key>NSName</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>31</integer>
+ </dict>
+ <key>NSSize</key>
+ <real>14</real>
+ <key>NSfFlags</key>
+ <integer>16</integer>
+ </dict>
+ <string>Courier</string>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSFont</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSFont</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDictionary</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDictionary</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>KBWordCountingTextStorage</string>
+ <string>NSTextStorage</string>
+ <string>NSMutableAttributedString</string>
+ <string>NSAttributedString</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>KBWordCountingTextStorage</string>
+ </dict>
+ <dict>
+ <key>$class</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>36</integer>
+ </dict>
+ <key>NS.time</key>
+ <real>267380389.206624</real>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSDate</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSDate</string>
+ </dict>
+ <dict>
+ <key>$classes</key>
+ <array>
+ <string>NSMutableArray</string>
+ <string>NSArray</string>
+ <string>NSObject</string>
+ </array>
+ <key>$classname</key>
+ <string>NSMutableArray</string>
+ </dict>
+ </array>
+ <key>$top</key>
+ <dict>
+ <key>Snapshots</key>
+ <dict>
+ <key>CF$UID</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>$version</key>
+ <integer>100000</integer>
+</dict>
+</plist>
diff --git a/doc/Ledger.scriv/ui.xml b/doc/Ledger.scriv/ui.xml
new file mode 100644
index 00000000..a81ce1ac
--- /dev/null
+++ b/doc/Ledger.scriv/ui.xml
@@ -0,0 +1,3529 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>.lockedInPlace</key>
+ <false/>
+ <key>binderSelection</key>
+ <array>
+ <integer>107</integer>
+ </array>
+ <key>binderSplitFrames</key>
+ <array>
+ <string>{{0, 0}, {218, 852}}</string>
+ <string>{{219, 0}, {986, 852}}</string>
+ </array>
+ <key>binderState</key>
+ <array>
+ <integer>0</integer>
+ <integer>4</integer>
+ <integer>6</integer>
+ <integer>8</integer>
+ <integer>12</integer>
+ <integer>13</integer>
+ <integer>16</integer>
+ <integer>28</integer>
+ <integer>44</integer>
+ <integer>54</integer>
+ <integer>55</integer>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>58</integer>
+ <integer>59</integer>
+ <integer>60</integer>
+ <integer>61</integer>
+ <integer>29</integer>
+ <integer>62</integer>
+ <integer>63</integer>
+ <integer>64</integer>
+ <integer>65</integer>
+ <integer>66</integer>
+ <integer>30</integer>
+ <integer>31</integer>
+ <integer>32</integer>
+ <integer>67</integer>
+ <integer>72</integer>
+ <integer>73</integer>
+ <integer>69</integer>
+ <integer>70</integer>
+ <integer>71</integer>
+ <integer>33</integer>
+ <integer>17</integer>
+ <integer>74</integer>
+ <integer>81</integer>
+ <integer>82</integer>
+ <integer>75</integer>
+ <integer>83</integer>
+ <integer>76</integer>
+ <integer>84</integer>
+ <integer>85</integer>
+ <integer>86</integer>
+ <integer>87</integer>
+ <integer>88</integer>
+ <integer>77</integer>
+ <integer>89</integer>
+ <integer>90</integer>
+ <integer>91</integer>
+ <integer>92</integer>
+ <integer>93</integer>
+ <integer>94</integer>
+ <integer>95</integer>
+ <integer>78</integer>
+ <integer>79</integer>
+ <integer>80</integer>
+ <integer>18</integer>
+ <integer>96</integer>
+ <integer>97</integer>
+ <integer>98</integer>
+ <integer>99</integer>
+ <integer>100</integer>
+ <integer>101</integer>
+ <integer>102</integer>
+ <integer>103</integer>
+ <integer>104</integer>
+ <integer>105</integer>
+ <integer>106</integer>
+ <integer>107</integer>
+ <integer>108</integer>
+ <integer>109</integer>
+ <integer>110</integer>
+ <integer>111</integer>
+ <integer>112</integer>
+ <integer>113</integer>
+ <integer>114</integer>
+ <integer>115</integer>
+ <integer>116</integer>
+ <integer>117</integer>
+ <integer>118</integer>
+ <integer>119</integer>
+ <integer>19</integer>
+ <integer>20</integer>
+ <integer>21</integer>
+ <integer>22</integer>
+ <integer>23</integer>
+ <integer>24</integer>
+ <integer>25</integer>
+ <integer>220</integer>
+ <integer>26</integer>
+ <integer>120</integer>
+ <integer>121</integer>
+ <integer>122</integer>
+ <integer>123</integer>
+ <integer>124</integer>
+ <integer>125</integer>
+ <integer>218</integer>
+ <integer>1</integer>
+ <integer>2</integer>
+ <integer>27</integer>
+ <integer>45</integer>
+ <integer>46</integer>
+ <integer>47</integer>
+ <integer>48</integer>
+ <integer>49</integer>
+ <integer>50</integer>
+ <integer>51</integer>
+ <integer>52</integer>
+ <integer>223</integer>
+ <integer>224</integer>
+ </array>
+ <key>closedSuccessfully</key>
+ <true/>
+ <key>editorSplitFrames</key>
+ <array>
+ <string>{{0, 0}, {785, 421}}</string>
+ <string>{{0, 431}, {785, 421}}</string>
+ </array>
+ <key>editorSplitType</key>
+ <integer>0</integer>
+ <key>ghostNotesMode</key>
+ <false/>
+ <key>iconsShowLabels</key>
+ <true/>
+ <key>inspectorIsCollapsed</key>
+ <false/>
+ <key>inspectorNotesMode</key>
+ <integer>1</integer>
+ <key>inspectorReferencesColumns</key>
+ <dict>
+ <key>order</key>
+ <array>
+ <string>ICON</string>
+ <string>DESCRIPTION</string>
+ <string>URL</string>
+ </array>
+ <key>widths</key>
+ <dict>
+ <key>DESCRIPTION</key>
+ <real>87</real>
+ <key>ICON</key>
+ <real>16</real>
+ <key>URL</key>
+ <real>88.4423828125</real>
+ </dict>
+ </dict>
+ <key>inspectorSelectedDataTab</key>
+ <integer>2</integer>
+ <key>inspectorSplitFrames</key>
+ <array>
+ <string>{{0, 0}, {785, 852}}</string>
+ <string>{{786, 0}, {200, 852}}</string>
+ </array>
+ <key>inspectorWidth</key>
+ <real>200</real>
+ <key>mainDocumentEditor.binderDocuments</key>
+ <array>
+ <integer>177</integer>
+ </array>
+ <key>mainDocumentEditor.corkboardVisible</key>
+ <false/>
+ <key>mainDocumentEditor.hiddenColumnIdentifiers</key>
+ <array>
+ <string>SYNOPSIS</string>
+ <string>CREATEDDATE</string>
+ <string>MODIFIEDDATE</string>
+ <string>WORDS</string>
+ <string>CHARACTERS</string>
+ <string>INCLUDEINEXPORT</string>
+ <string>PAGEBREAKBEFORE</string>
+ <string>PRESERVEFORMAT</string>
+ <string>TARGETTYPE</string>
+ <string>TOTALCHARACTERS</string>
+ </array>
+ <key>mainDocumentEditor.lockedInPlace</key>
+ <false/>
+ <key>mainDocumentEditor.navHistory</key>
+ <dict>
+ <key>CurrentIndex</key>
+ <integer>533</integer>
+ <key>NavigationHistoryArray</key>
+ <array>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>3</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>1</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>0</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>4</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>5</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>4</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>0</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>6</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>7</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>6</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>8</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>0</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>4</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>5</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>6</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>7</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>8</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>9</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>8</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>10</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>11</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>1</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>10</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>1</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>6</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>12</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>13</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>12</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>13</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>12</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>13</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>12</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>14</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>13</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>15</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>13</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>15</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>0</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>16</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>17</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>18</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>19</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>20</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>21</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>22</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>24</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>25</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>26</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>27</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>16</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>17</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>18</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>19</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>20</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>21</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>22</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>23</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>24</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>25</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>26</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>27</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>1</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>16</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>28</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>29</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>30</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>31</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>32</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>33</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>16</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>28</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>16</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>0</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>16</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>126</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>28</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>127</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>44</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>128</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>54</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>129</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>55</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>130</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>56</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>131</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>57</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>132</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>58</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>133</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>59</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>134</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>60</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>135</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>61</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>136</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>29</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>137</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>62</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>138</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>63</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>139</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>64</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>140</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>65</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>141</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>66</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>142</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>139</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>140</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>141</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>142</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>63</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>139</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>64</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>140</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>65</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>141</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>66</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>142</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>30</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>143</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>31</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>144</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>32</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>145</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>32</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>145</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>67</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>146</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>72</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>147</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>73</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>148</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>69</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>70</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>71</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>70</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>69</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>148</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>69</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>149</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>70</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>150</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>71</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>151</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>67</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>146</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>72</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>147</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>73</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>72</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>148</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>69</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>149</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>70</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>150</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>71</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>151</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>33</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>152</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>32</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>17</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>20</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>17</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>153</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>154</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>74</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>155</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>81</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>82</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>81</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>156</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>82</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>157</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>75</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>158</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>83</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>159</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>76</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>160</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>84</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>161</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>85</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>162</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>86</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>163</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>164</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>163</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>164</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>87</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>88</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>87</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>165</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>88</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>166</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>77</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>167</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>168</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>167</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>168</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>77</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>168</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>89</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>169</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>90</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>170</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>91</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>171</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>92</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>172</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>93</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>173</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>94</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>174</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>95</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>175</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>78</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>176</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>79</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>177</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>80</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>178</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>18</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>179</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>96</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>180</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>97</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>181</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>98</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>182</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>99</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>183</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>100</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>184</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>101</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>185</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>102</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>186</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>185</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>103</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>104</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>105</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>106</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>107</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>108</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>107</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>21</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>103</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>187</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>104</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>188</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>105</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>189</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>106</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>190</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>107</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>191</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>108</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>192</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>109</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>193</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>110</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>194</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>111</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>195</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>112</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>196</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>113</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>197</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>114</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>198</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>115</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>199</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>116</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>200</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>117</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>201</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>118</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>202</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>119</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>203</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>19</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>204</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>20</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>205</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>21</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>206</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>22</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>207</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>23</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>208</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>24</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>209</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>25</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>210</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>26</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>211</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>120</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>212</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>121</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>213</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>122</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>214</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>123</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>215</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>124</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>216</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>125</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>217</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>17</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>153</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>74</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>155</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>81</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>156</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>155</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>82</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>157</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>75</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>158</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>83</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>159</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>76</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>160</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>84</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>161</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>160</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>85</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>162</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>86</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>164</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>87</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>165</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>88</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>166</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>77</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>168</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>89</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>169</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>90</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>170</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>91</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>171</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>170</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>92</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>172</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>93</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>173</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>94</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>173</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>94</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>174</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>95</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>78</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>175</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>78</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>176</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>79</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>177</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>80</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>178</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>18</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>179</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>96</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>179</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>96</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>180</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>97</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>181</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>98</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>182</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>99</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>183</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>100</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>184</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>101</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>186</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>102</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>185</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>187</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>104</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>103</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>104</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>188</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>105</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>189</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>106</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>190</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>107</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>191</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>108</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>192</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>109</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>193</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>110</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>194</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>111</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>195</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>112</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>196</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>113</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>197</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>114</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>198</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>115</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>199</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>198</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>116</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>200</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>117</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>201</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>118</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>202</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>119</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>203</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>19</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>204</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>20</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>205</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>21</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>206</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>22</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>207</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>208</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>24</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>23</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>24</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>25</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>26</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>211</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>120</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>26</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>211</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>120</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>212</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>121</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>120</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>121</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>213</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>122</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>214</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>123</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>215</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>124</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>123</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>124</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>125</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>4</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>5</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>4</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>5</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>4</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>0</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>218</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>168</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>4</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>6</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>4</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>6</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>12</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>13</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>16</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>17</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>18</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>19</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>20</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>21</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>20</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>21</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>22</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>21</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>20</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>18</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>16</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>13</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>6</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>4</integer>
+ <key>Mode</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>0</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>4</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>0</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>8</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>9</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>7</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>25</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>219</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>220</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>220</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>219</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>25</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>220</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>220</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>220</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>223</integer>
+ <key>Mode</key>
+ <integer>1</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>25</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>219</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>221</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>220</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>219</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>25</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>24</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>23</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>22</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>21</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>20</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>9</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>222</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>177</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>79</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>BinderDocID</key>
+ <integer>177</integer>
+ <key>Mode</key>
+ <integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ <key>mainDocumentEditor.outlinerColumnsState</key>
+ <dict>
+ <key>order</key>
+ <array>
+ <string>TITLE</string>
+ <string>TYPE</string>
+ <string>LABEL</string>
+ <string>STATUS</string>
+ <string>TOTALWORDS</string>
+ <string>TARGET</string>
+ <string>PROGRESS</string>
+ <string>SYNOPSIS</string>
+ <string>CREATEDDATE</string>
+ <string>MODIFIEDDATE</string>
+ <string>WORDS</string>
+ <string>CHARACTERS</string>
+ <string>INCLUDEINEXPORT</string>
+ <string>PAGEBREAKBEFORE</string>
+ <string>PRESERVEFORMAT</string>
+ <string>TARGETTYPE</string>
+ <string>TOTALCHARACTERS</string>
+ </array>
+ <key>widths</key>
+ <dict>
+ <key>CHARACTERS</key>
+ <real>46</real>
+ <key>CREATEDDATE</key>
+ <real>53</real>
+ <key>INCLUDEINEXPORT</key>
+ <real>10</real>
+ <key>LABEL</key>
+ <real>105</real>
+ <key>MODIFIEDDATE</key>
+ <real>50</real>
+ <key>PAGEBREAKBEFORE</key>
+ <real>66</real>
+ <key>PRESERVEFORMAT</key>
+ <real>110.841796875</real>
+ <key>PROGRESS</key>
+ <real>49</real>
+ <key>STATUS</key>
+ <real>84</real>
+ <key>SYNOPSIS</key>
+ <real>140</real>
+ <key>TARGET</key>
+ <real>50</real>
+ <key>TARGETTYPE</key>
+ <real>50</real>
+ <key>TITLE</key>
+ <real>326</real>
+ <key>TOTALCHARACTERS</key>
+ <real>96</real>
+ <key>TOTALWORDS</key>
+ <real>72</real>
+ <key>TYPE</key>
+ <real>43</real>
+ <key>WORDS</key>
+ <real>40</real>
+ </dict>
+ </dict>
+ <key>mainDocumentEditor.outlinerSelection</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGCQpYJHZlcnNpb25UJHRvcFkkYXJjaGl2ZXJYJG9iamVjdHMS
+ AAGGoNEHCFRyb290gAFfEA9OU0tleWVkQXJjaGl2ZXKjCwwRVSRudWxs0g0ODxBWJGNs
+ YXNzXE5TUmFuZ2VDb3VudIACEADSEhMUFVgkY2xhc3Nlc1okY2xhc3NuYW1lohUWWk5T
+ SW5kZXhTZXRYTlNPYmplY3QIERofKTI3Oj9BU1ddYml2eHp/iJOWoQAAAAAAAAEBAAAA
+ AAAAABcAAAAAAAAAAAAAAAAAAACq
+ </data>
+ <key>mainDocumentEditor.outlinerState</key>
+ <array>
+ <integer>220</integer>
+ </array>
+ <key>mainDocumentEditor.outlinerVisible</key>
+ <false/>
+ <key>mainDocumentEditor.textMode</key>
+ <integer>0</integer>
+ <key>mainWindowFrame</key>
+ <string>40 4 1205 874 0 0 1440 878 </string>
+ <key>projectStatsSheet</key>
+ <dict>
+ <key>excludeAnnots</key>
+ <true/>
+ <key>excludeFN</key>
+ <false/>
+ <key>includeSubdocs</key>
+ <true/>
+ <key>limitLinesPerPage</key>
+ <false/>
+ <key>lineCountingFont</key>
+ <data>
+ BAtzdHJlYW10eXBlZIHoA4QBQISEhAZOU0ZvbnQehIQITlNPYmplY3QAhYQB
+ aRiEBVsyNGNdBgAAABAAAAD//kMAbwB1AHIAaQBlAHIAhAFmDIQBYwCYAZgA
+ mACG
+ </data>
+ <key>maxLinesPerPage</key>
+ <integer>54</integer>
+ <key>options</key>
+ <integer>0</integer>
+ <key>wordsPerPaperbackPage</key>
+ <integer>350</integer>
+ </dict>
+ <key>showInvisibles</key>
+ <false/>
+ <key>supportingDocumentEditor.binderDocuments</key>
+ <array/>
+ <key>supportingDocumentEditor.lockedInPlace</key>
+ <false/>
+ <key>supportingDocumentEditor.navHistory</key>
+ <dict>
+ <key>CurrentIndex</key>
+ <integer>-1</integer>
+ <key>NavigationHistoryArray</key>
+ <array/>
+ </dict>
+ <key>supportingDocumentEditor.textMode</key>
+ <integer>0</integer>
+ <key>supportingDocumentViewIsCurrent</key>
+ <false/>
+ <key>tintIndexCardsWithLabelColor</key>
+ <true/>
+ <key>tintOutlinerRowsWithLabelColor</key>
+ <false/>
+</dict>
+</plist>
diff --git a/NEWS b/doc/NEWS
index ac56c581..b07fe2ec 100644
--- a/NEWS
+++ b/doc/NEWS
@@ -1,8 +1,156 @@
Ledger NEWS
+* 3.0
+
+** INCOMPATIBLE CHANGES
+
+*** Commands
+
+**** Removed 'output'
+**** Removed 'xml'
+
+*** Options
+
+**** --descend
+**** --descend_if EXPR
+**** --reconcile
+**** --reconcile-date DATE
+
+**** -s, -n
+
+The balance report now defaults to showing all relevant accounts. This is the
+opposite of how it worked before. That is, "bal" in 3.0 does what "-s bal"
+did in 2.x. To get the 2.6 behavior, use "bal -n" in 3.0. The -s option no
+longer has any effect on balance reports.
+
+** NEW FEATURES
+
+*** Commands
+
+*** Options
+
+**** --anon
+
+For anonymizing the private details of reports. This is almost solely for the
+purpose of easing the creation of accurate bug reports.
+
* 2.6.1
-- This version has no new features, it's all bug fixes.
+- Added the concept of "balance setting transactions":
+
+ # Setting an account's balance
+
+ You can now manually set an account's balance to whatever you want, at
+ any time. Here's how it might look at the beginning of your Ledger
+ file:
+
+ 2008/07/27 Starting fresh
+ Assets:Checking = $1,000.00
+ Equity:Opening Balances
+
+ If Assets:Checking is empty, this is no different from omitting the
+ "=". However, if Assets:Checking did have a prior balance, the amount
+ of the transaction will be auto-calculated so that the final balance
+ of Assets:Checking is now $1,000.00.
+
+ Let me give an example of this. Say you have this:
+
+ 2008/07/27 Starting fresh
+ Assets:Checking $750.00
+ Equity:Opening Balances
+
+ 2008/07/27 Starting fresh
+ Assets:Checking = $1,000.00
+ Equity:Adjustments
+
+ These two entries are exactly equivalent to these two:
+
+ 2008/07/27 Starting fresh
+ Assets:Checking $750.00
+ Equity:Opening Balances
+
+ 2008/07/27 Starting fresh
+ Assets:Checking $250.00
+ Equity:Adjustments
+
+ The use of the "=" sign here is that it sets the transaction's amount
+ to whatever is required to satisfy the assignment. This is the
+ behavior if the transaction's amount is left empty.
+
+ # Multiple commodities
+
+ As far as commodities go, the = sign only works if the account
+ balance's commodity matches the commodity of the amount after the
+ equals sign. However, if the account has multiple commodities, only
+ the matching commodity is affected. Here's what I mean:
+
+ 2008/07/24 Opening Balance
+ Assets:Checking = $250.00 ; we force set it
+ Equity:Opening Balances
+
+ 2008/07/24 Opening Balance
+ Assets:Checking = EC 250.00 ; we force set it again
+ Equity:Opening Balances
+
+ This is an error, because $250.00 cannot be auto-balanced to match EC
+ 250.00. However:
+
+ 2008/07/24 Opening Balance
+ Assets:Checking = $250.00 ; we force set it again
+ Assets:Checking EC 100.00 ; and add some EC's
+ Equity:Opening Balances
+
+ 2008/07/24 Opening Balance
+ Assets:Checking = EC 250.00 ; we force set the EC's
+ Equity:Opening Balances
+
+ This is *not* an error, because the latter auto-balancing transaction
+ only affects the EC 100.00 part of the account's balance; the $250.00
+ part is left alone.
+
+ # Checking statement balances
+
+ When you reconcile a statement, there are typically one or more
+ transactions which result in a known balance. Here's how you specify
+ that in your Ledger data:
+
+ 2008/07/24 Opening Balance
+ Assets:Checking = $100.00
+ Equity:Opening Balances
+
+ 2008/07/30 We spend money, with a known balance afterward
+ Expenses:Food $20.00
+ Assets:Checking = $80.00
+
+ 2008/07/30 Again we spend money, but this time with all the info
+ Expenses:Food $20.00
+ Assets:Checking $-20.00 = $60.00
+
+ 2008/07/30 This entry yield an 'unbalanced' error
+ Expenses:Food $20.00
+ Assets:Checking $-20.00 = $30.00
+
+ The last entry in this set fails to balance with an unbalanced
+ remainder of $-10.00. Either the entry must be corrected, or you can
+ have Ledger deal with the remainder automatically:
+
+ 2008/07/30 The fixed entry
+ Expenses:Food $20.00
+ Assets:Checking $-20.00 = $30.00
+ Equity:Adjustments
+
+ # Conclusion
+
+ This simple feature has all the utility of @check, plus auto-balancing
+ to match known target balances, plus the ability to guarantee that an
+ account which uses only one commodity does contain only that
+ commodity.
+
+ This feature slows down textual parsing slightly, does not affect
+ speed when loading from the binary cache.
+
+- The rest of the changes in the version is all bug fixes (around 45 of
+ them).
* 2.6.0.90
diff --git a/README b/doc/README
index 8a2406d9..8f83ef39 100644
--- a/README
+++ b/doc/README
@@ -6,53 +6,44 @@
Introduction
============
-Ledger is an accounting program which is invoked from the command-line
-using a textual ledger file. To start using Ledger, you will need to
-create such a file containing your financial transactions. A sample
-has been provided in the file "sample.dat". See the documentation
-(ledger.pdf, or ledger.info) for full documentation on creating a
-ledger file and using Ledger to generate reports.
+Ledger is an accounting program which is invoked from the command-line using a
+textual ledger file. To start using Ledger, you will need to create such a
+file containing your financial postings. A sample has been provided in the
+file "sample.dat". See the documentation (ledger.pdf, or ledger.info) for
+full documentation on creating a ledger file and using Ledger to generate
+reports.
-Once you have such a file -- you might call it "ledger.dat" -- you can
-start looking at balances and account registers using commands like
-the following:
+Once you have such a file -- you might call it "ledger.dat" -- you can start
+looking at balances and account registers using commands like the following:
ledger -f ledger.dat balance assets:checking
ledger -f ledger.dat register expenses:food
-This assumes, of course, that like the sample file you use account
-names such as "Assets:Checking" and "Expenses:Food". If you use other
-account names, you will need to vary the reporting commands you use
-accordingly.
+This assumes, of course, that like the sample file you use account names such
+as "Assets:Checking" and "Expenses:Food". If you use other account names, you
+will need to vary the reporting commands you use accordingly.
Building
========
-To build Ledger, you will need a fairly modern C++ compiler (gcc 2.95
-will not work), and at least these two libraries installed:
+To build Ledger, you will need a fairly modern C++ compiler (gcc 2.95 will not
+work), and at least these two libraries installed:
gmp GNU multi-precision library
pcre Perl regular expression library
-(On some GNU/Linux systems, the packages you need to install are
-called "gmp-dev" and "pcre-dev").
-
-If you wish to read Gnucash data files, you will also need two XML
-libraries, which may or may not be available in a single package (it
-depends on your distribution):
-
- libexpat, or libxmlparse and libxmltok
+(On some GNU/Linux systems, the packages you need to install are called
+"gmp-dev" and "pcre-dev").
Once you have determined where the headers and libraries for the above
-packages are installed, run the script "configure", passing those
-paths. If you installed everything under /usr/local, you can probably
-just type "./configure". Otherwise, do this:
+packages are installed, run the script "configure", passing those paths. If
+you installed everything under /usr/local, you can probably just type
+"./configure". Otherwise, do this:
./configure CPPFLAGS=-I<INCLUDE-PATH> LDFLAGS=-L<LIBRARY-PATH>
-If you need to specify multiple include or library paths, then do
-this:
+If you need to specify multiple include or library paths, then do this:
./configure CPPFLAGS="-I<PATH1> -I<PATH2>" LDFLAGS="-L<PATH1> -L<PATH2>"
@@ -64,10 +55,10 @@ Once configure is done running, just type:
Mailing List and IRC
====================
-If you need help on how to use Ledger, or run into problems, you can
-join the Ledger mailing list at the following Web address:
+If you need help on how to use Ledger, or run into problems, you can join the
+Ledger mailing list at the following Web address:
- https://lists.sourceforge.net/lists/listinfo/ledger-discuss
+ http://groups.google.com/group/ledger-cli
You can also find help at the #ledger channel on the IRC server
irc.freenode.net.
diff --git a/doc/grammar.y b/doc/grammar.y
new file mode 100644
index 00000000..018e7391
--- /dev/null
+++ b/doc/grammar.y
@@ -0,0 +1,221 @@
+/**
+ * @file grammar.y
+ * @version 3.0
+ * @author John Wiegley
+ *
+ * @brief Canonical BNF grammar for Ledger data files
+ *
+ * Extensions are permitted if: they are not required, and they are
+ * backwards-compatible with this grammar.
+ */
+
+/*
+ * There are three special terminals in this grammar, which violate its
+ * context free nature:
+ *
+ * TEXT -- consumes all characters until the next terminal
+ * or EOL (end of line)
+ * WHITESPACE -- any amount of whitespace, not including EOL
+ * STRING -- characters up to the next WHITESPACE or EOL
+ *
+ * BIGINT -- a number of any width, matching [0-9]+
+ * INT4 -- a four digit wide number
+ * INT2 -- a two digit wide number
+ * INT1 -- a one digit wide number
+ *
+ * Except for 1) the 'spacer' production (see below), 2) EOL, and 3) the
+ * WHITESPACE required to begin a posting, whitespace is otherwise
+ * ignored.
+ *
+ * Yes, this grammar is confusing and not so happy for machine readers,
+ * but it was designed for the human author and reader. Once parsed,
+ * the contents must be unambiguous, which means they can be output to
+ * more rigorous formats for other programs to consume.
+ */
+
+/*
+ * Journals
+ *
+ * A journal is a file which primarily contains xacts, among other elements.
+ */
+
+journal:
+ journal_item journal |
+ /* epsilon */
+ ;
+
+journal_item:
+ whitespace
+ directive |
+ xact |
+ ;
+
+whitespace:
+ EOL |
+ WHITESPACE EOL |
+ ';' TEXT EOL | /* these next four are all ignored */
+ '*' TEXT EOL |
+ ;
+
+directive:
+ '@' word_directive EOL |
+ '!' word_directive EOL |
+ word_directive EOL |
+ char_directive EOL
+ ;
+
+word_directive:
+ "include" TEXT |
+ "account" TEXT |
+ "end" |
+ "alias" STRING '=' TEXT |
+ "def" TEXT |
+ TEXT WHITESPACE TEXT /* looked up in session (aka maybe Python) */
+ ;
+
+char_directive:
+ 'i' date time TEXT | /* a timeclock.el "check in" */
+ 'I' date time TEXT |
+ 'o' date time TEXT | /* a timeclock.el "check out" */
+ 'O' date time TEXT |
+ 'h' TEXT EOL |
+ 'b' TEXT EOL |
+ 'D' amount | /* sets display parameters for a commodity */
+ 'A' TEXT | /* sets the "default balancing account" */
+ 'C' commodity '=' amount | /* specifies a commodity conversion */
+ 'P' date time commodity amount | /* a pricing history xact */
+ 'N' commodity | /* commodity's price is never downloaded */
+ 'Y' INT4 | /* sets the default year for date parsing */
+ '-' '-' STRING TEXT | /* specify command-line options in the file */
+ ;
+
+date: INT4 date_sep INT2 date_sep INT2 ;
+date_opt: '=' date | /* epsilon */ ;
+date_sep: '/' | '-' | '.' ;
+
+time: INT2 ':' INT2 ':' INT2 ;
+
+commodity:
+ '"' TEXT '"' |
+ STRING ;
+
+/*
+ * Xacts
+ *
+ * Xacts are the atomic units of accounting, which are composed of
+ * multiple postings between accounts, so long as it all balances in
+ * the end.
+ */
+
+xact: plain_xact |
+ periodic_xact |
+ automated_xact ;
+
+plain_xact:
+ date date_opt status_opt code_opt FULLSTRING note_opt EOL
+ postings ;
+
+status_opt: status | /* epsilon */ ;
+status: '*' | '!' | /* epsilon */ ;
+
+code_opt: code | /* epsilon */ ;
+code: '(' TEXT ')' ;
+
+spacer: ' ' ' ' | '\t' | ' ' '\t' ;
+
+note_opt: spacer note | /* epsilon */ ;
+note: ';' TEXT ;
+
+/* ---------------------------------------------------------------------- */
+
+periodic_xact:
+ '~' period_expr note_opt EOL
+ posting postings ;
+
+/*
+ * A period expression has its own sub-grammar, which I don't quite have
+ * the time to exhaustively describe now. See datetime.cc. It allows
+ * for lots and lots of things, and is probably horribly ambiguous.
+ */
+
+period_expr: FULLSTRING ;
+
+/* ---------------------------------------------------------------------- */
+
+automated_xact:
+ '=' value_expr note_opt EOL
+ posting postings ;
+
+/*
+ * Value expressions are a algebraic math expressions very similar to
+ * XPath (minus the path traversal items). This grammar needs fleshing
+ * out also, since it's allowed in many places.
+ */
+
+value_expr: FULLSTRING ;
+
+/*
+ * There is a serious ambiguity here which the parser resolves as
+ * follows: if an amount_expr can be parsed as an amount, it's an
+ * amount; otherwise, it's a value expression.
+ */
+
+quantity: neg_opt BIGINT decimal_opt ;
+
+neg_opt: '-' | /* epsilon */ ;
+decimal_opt: '.' BIGINT | /* epsilon */ ;
+
+annotation: lot_price_opt lot_date_opt lot_note_opt ;
+
+lot_date_opt: date | /* epsilon */ ;
+lot_date: '[' date ']' ;
+
+lot_price_opt: price | /* epsilon */ ;
+lot_price: '{' amount '}' ;
+
+lot_note_opt: note | /* epsilon */ ;
+lot_note: '(' string ')' ;
+
+amount:
+ neg_opt commodity quantity annotation |
+ quantity commodity annotation ;
+
+amount_expr: amount | value_expr ;
+
+/*
+ * Postings
+ *
+ * Postings are the fundamental unit of accounting, and represent
+ * the movement of commodities to or from an account. Thus, paying off
+ * your credit card consists of two balancing postings: one that
+ * withdraws money from your checking account, and another which pays
+ * money to your credit institution.
+ */
+
+postings:
+ posting postings |
+ /* epsilon */
+ ;
+
+posting:
+ WHITESPACE status_opt account values_opt note_opt EOL;
+
+account_name: FULLSTRING ;
+
+values_opt:
+ spacer amount_expr price_opt |
+ /* epsilon */
+ ;
+
+price_opt: price | /* epsilon */ ;
+price:
+ '@' amount_expr |
+ '@@' amount_expr /* in this case, it's the whole price */
+ ;
+
+account:
+ account_name |
+ '(' account_name ')' |
+ '[' account_name ']' ;
+
+/* grammar.y ends here */
diff --git a/doc/ledger.1 b/doc/ledger.1
new file mode 100644
index 00000000..92457c48
--- /dev/null
+++ b/doc/ledger.1
@@ -0,0 +1,583 @@
+.Dd November 13, 2009
+.Dt ledger 1
+.Sh NAME
+.Nm ledger
+.Nd Command-line, double-entry account reporting tool
+.Sh SYNOPSIS
+ledger
+.Op Ar command
+.Op Ar options
+.Op Ar arguments
+.Sh DESCRIPTION
+Ledger is a command-line accounting tool based on the power and completeness
+of double-entry accounting. It is only a reporting tool, which means it never
+modifies your data files, but it does offers a large selection of reports, and
+different ways to customize them to your liking.
+.Pp
+.Sh COMMANDS
+Ledger accepts several top-level commands, each of which generates a different
+kind of basic report. Most of them accept a
+.Ar report-query
+argument, in order to determine what should be reported. To understand the
+syntax of a
+.Ar report-query ,
+see the section on
+.Sx QUERIES .
+In its most basic form, simply specifying one or more strings produces a
+report for all accounts containing those strings.
+.Pp
+If no command is given, Ledger enters a
+.Tn REPL ,
+or command loop, allowing several commands to be executed against the same
+dataset without reparsing.
+.Pp
+The following is a complete list of reporting commands accepted by Ledger:
+.Pp
+.Bl -tag -width balance
+.It Nm balance Oo Ar report-query Oc
+Produces a balance report showing totals for all matching accounts, and
+aggregate totals for parents of those accounts. Options most commonly used
+with this command are:
+.Pp
+.Bl -tag -compact -width "--collapse (-n)"
+.It Fl \-basis Pq Fl B
+Report in terms of cost basis, not amount or value. This is the only form of
+report which is guaranteed to always balance to zero, when no
+.Ar report-query
+is specified.
+.It Fl \-collapse Pq Fl n
+Only show totals for the top-most accounts.
+.It Fl \-empty Pq Fl E
+Also show accounts whose total is zero.
+.It Fl \-flat
+Rather than display a hierarchical tree, flatten the report to show subtotals
+for only accounts matching
+.Ar report-query .
+.It Fl \-no\-total
+Suppress the summary total shown at the bottom of the report (when not zero).
+.El
+.Pp
+The synonyms
+.Nm bal
+and
+.Nm b
+are also accepted.
+.It Nm budget Oo Ar report-query Oc
+A special balance report which includes three extra columns: the amount
+budgeted during the reporting period, how spending differed from the budget,
+and the percentage of budget spent (exceeds 100% if you go over budget).
+Note that budgeting requires one or more
+.Do
+periodic transactions
+.Dc
+to be defined in your data file(s). See the manual for more information.
+.It Nm cleared Oo Ar report-query Oc
+A special balance report which adds two extra columns: the cleared balance for
+each account, and the date of the most recent cleared posting in that account.
+For this accounting to be meaningful, the cleared flag must be set on at least
+one posting. See the manual for more information.
+.It Nm csv Oo Ar report-query Oc
+Report of postings matching the
+.Ar report-query
+in CSV format (comma-separated values). Useful for exporting data to a
+spreadsheet for further analysis or charting.
+.It Nm draft Oo Ar draft-template Oc
+Generate and display a new, properly formatted Ledger transaction by comparing
+the
+.Ar draft-template
+to the transactions in your data file(s). For more information on draft
+templates and using this command to quickly create new transactions, see the
+section
+.Sx DRAFTS .
+.Pp
+The synonyms
+.Nm entry
+and
+.Nm xact
+are also accepted.
+.It Nm emacs Oo Ar query Oc
+Outputs posting and transaction data in a format readily consumed by the Emacs
+editor, in a series of Lisp forms. This is used by the
+.Li ledger.el
+Emacs mode to process reporting data from Ledger.
+.Pp
+The synonym
+.Nm lisp
+is also accepted.
+.It Nm equity Oo Ar report-query Oc
+Prints a series of transactions that balance current totals for
+accounts matching the
+.Ar report-query
+in a special account called
+.Li Equity:Opening Balances .
+The purpose of this report is to close the books for a prior year, while using
+these equity transactions to carry forward those balances.
+.It Nm prices Oo Ar report-query Oc
+Reports prices for all commodities in postings matching the
+.Ar report-query .
+The prices are reported with the granularity of a single day.
+.It Nm pricesdb Oo Ar report-query Oc
+Reports prices for all commodities in postings matching the
+.Ar report-query .
+Prices are reported down to the second, using the same format as the
+.Li ~/.pricedb
+file.
+.It Nm print Oo Ar report-query Oc
+Prints out the full transactions of any matching postings using the same
+format as they would appear in a data file. This can be used to extract
+subsets from a Ledger file to transfer to other files.
+.It Nm push Oo Ar options Oc
+In the
+.Tn REPL ,
+this command pushes a set of command-line options, so that they will apply to
+all subsequent reports.
+.It Nm pop
+In the
+.Tn REPL ,
+pops any option settings that have been pushed.
+.It Nm register Oo Ar report-query Oc
+List all postings matching the
+.Ar report-query .
+This is one of the most common commands, and can be used to provide a variety
+of useful reports. Options most commonly used
+with this command are:
+.Pp
+.Bl -tag -compact -width "--collapse (-n)"
+.It Fl \-average Pq Fl A
+Show the running average, rather than a running total.
+.It Fl \-current Pq Fl c
+Don't show postings beyond the present day.
+.It Fl \-exchange Ar commodity Pq Fl X
+Render all values in the given
+.Ar commodity ,
+if a price conversion rate can be determined. Rates are always displayed
+relative to the date of the posting they are calculated for. This means a
+.Nm register
+report is a historical value report. For current values, it may be preferable
+to use the
+.Nm balance
+report.
+.It Fl \-gain Pq Fl G
+Show any gains (or losses) in commodity values over time.
+.It Fl \-head Ar number
+Only show the top
+.Ar number
+postings.
+.It Fl \-invert
+Invert the value of amounts shown.
+.It Fl \-market Pq Fl V
+Show current market values for all amounts. This is determined in a somewhat
+magical fashion. It is probably more straightforward to use
+.Fl \-exchange Pq Fl X .
+.It Fl \-period Ar time-period Pq Fl p
+Show postings only for the given
+.Ar time-period .
+.It Fl \-related Pq Fl r
+Show postings that are related to those that would have been shown. It has
+the effect of displaying the
+.Do
+other side
+.Dc
+of the values.
+.It Fl \-sort Ar value-expression Pq Fl S
+Sort postings by evaluating the given
+.Ar value-expression .
+Note that a comma-separated list of expressions is allowed, in which case each
+sorting term is used in order to determine the final ordering. For example,
+to search by date and then amount, one would use:
+.Li -S 'date, amount' .
+.It Fl \-tail Ar number
+Only show the last
+.Ar number
+postings.
+.It Fl \-uncleared Pq Fl U
+Only show uncleared (i.e., recent) postings.
+.El
+.Pp
+There are also several grouping options that can be useful:
+.Pp
+.Bl -tag -compact -width "--collapse (-n)"
+.It Fl \-by-payee Pq Fl P
+Group postings by common payee names.
+.It Fl \-daily Pq Fl D
+Group postings by day.
+.It Fl \-weekly Pq Fl W
+Group postings by week (starting on Sundays).
+.It Fl \-start-of-week Ar day-name
+Set the start of each grouped way to the given
+.Ar day-name .
+.It Fl \-monthly Pq Fl M
+Group postings by month.
+.It Fl \-quarterly
+Group postings by fiscal quarter.
+.It Fl \-yearly Pq Fl Y
+Group postings by year.
+.It Fl \-dow
+Group postings by the day of the week on which they took place.
+.It Fl \-subtotal Pq Fl s
+Group all postings together. This is very similar to the totals shown by the
+.Nm balance
+report.
+.El
+.Pp
+The synonyms
+.Nm reg
+and
+.Nm r
+are also accepted.
+.It Nm server
+This command requires that Python support be active. If so, it starts up an
+HTTP server listening for requests on port 9000. This provides an alternate
+interface to creating and viewing reports. Note that this is very much a
+work-in-progress, and will not be fully functional until a later version.
+.It Nm stats Oo Ar report-query Oc
+Provides summary information about all the postings matching
+.Ar report-query .
+It provides information such as:
+.Bl -bullet -offset indent -compact
+.It
+Time range of all matching postings
+.It
+Unique payees
+.It
+Unique accounts
+.It
+Postings total
+.It
+Uncleared postings
+.It
+Days since last posting
+.It
+More...
+.El
+.It Nm xml Oo Ar report-query Oc
+Outputs data relating to the current report in XML format. It includes all
+accounts and commodities involved in the report, plus the postings and the
+transactions they are contained in. See the manual for more information.
+.El
+.Pp
+.Sh OPTIONS
+.Pp
+.Bl -tag -width -indent
+.It Fl \-abbrev-len Ar INT
+.It Fl \-account Ar STR
+.It Fl \-account-width Ar INT
+.It Fl \-actual Pq Fl L
+.It Fl \-add-budget
+.It Fl \-amount Ar EXPR Pq Fl t
+.It Fl \-amount-data Pq Fl j
+.It Fl \-amount-width Ar INT
+.It Fl \-anon
+.It Fl \-args-only
+.It Fl \-average Pq Fl A
+.It Fl \-balance-format Ar FMT
+.It Fl \-base
+.It Fl \-basis Pq Fl B
+.It Fl \-begin Ar DATE Pq Fl b
+.It Fl \-budget
+.It Fl \-by-payee Pq Fl P
+.It Fl \-cleared Pq Fl C
+.It Fl \-code-as-account
+.It Fl \-code-as-payee
+.It Fl \-collapse Pq Fl n
+.It Fl \-collapse-if-zero
+.It Fl \-color
+.It Fl \-columns Ar INT
+.It Fl \-commodity-as-account
+(Also
+.Fl \-\-comm\-as\-account
+).
+.It Fl \-commodity-as-payee
+(Also
+.Fl \-\-comm\-as\-payee
+).
+.It Fl \-cost
+See
+.Fl \-basis .
+.It Fl \-csv-format Ar FMT
+.It Fl \-current Pq Fl c
+.It Fl \-daily
+.It Fl \-date-format Ar DATEFMT Pq Fl y
+.It Fl \-date-width Ar INT
+.It Fl \-debug Ar STR
+.It Fl \-depth Ar INT
+.It Fl \-deviation Pq Fl D
+.It Fl \-display Ar EXPR Pq Fl d
+.It Fl \-display-amount Ar EXPR
+.It Fl \-display-total Ar EXPR
+.It Fl \-dow
+.It Fl \-download
+.It Fl \-effective
+.It Fl \-empty Pq Fl E
+.It Fl \-end Pq Fl e
+.It Fl \-equity
+.It Fl \-exact
+.It Fl \-exchange Ar COMM Oo , COMM, ... Oc Pq Fl X
+.It Fl \-file Ar FILE
+.It Fl \-first Ar INT
+See
+.Fl \-head .
+.It Fl \-flat
+.It Fl \-forecast-while Ar EXPR
+(Also
+.Fl \-forecast
+).
+.It Fl \-format Ar FMT Pq Fl F
+.It Fl \-gain Pq Fl G
+.It Fl \-head Ar INT
+.It Fl \-init-file Ar FILE
+.It Fl \-input-date-format Ar DATEFMT
+.It Fl \-invert
+.It Fl \-last Ar INT
+See
+.Fl \-tail .
+.It Fl \-leeway Ar INT Pq Fl Z
+.It Fl \-limit Ar EXPR Pq Fl l
+.It Fl \-lot-dates
+.It Fl \-lot-prices
+.It Fl \-lot-tags
+.It Fl \-lots
+.It Fl \-lots-actual
+.It Fl \-market Pq Fl V
+.It Fl \-monthly Pq Fl M
+.It Fl \-only Ar EXPR
+.It Fl \-output Ar FILE Pq Fl o
+.It Fl \-pager Ar STR
+.It Fl \-payee-as-account
+.It Fl \-payee-width Ar INT
+.It Fl \-pending
+.It Fl \-percentage Pq Fl \%
+.It Fl \-period Ar PERIOD Pq Fl p
+.It Fl \-period-sort
+.It Fl \-plot-amount-format Ar FMT
+.It Fl \-plot-total-format Ar FMT
+.It Fl \-price Pq Fl I
+.It Fl \-price-db Ar FILE
+.It Fl \-price-exp Ar STR
+See
+.Fl \-leeway .
+.It Fl \-prices-format Ar FMT
+.It Fl \-pricesdb-format Ar FMT
+.It Fl \-print-format Ar FMT
+.It Fl \-quantity Pq Fl O
+.It Fl \-quarterly
+.It Fl \-raw
+For use only with the
+.Nm print
+command, it causes Ledger to print out matching entries exactly as they
+appeared in the original journal file.
+.It Fl \-real Pq Fl R
+.It Fl \-register-format Ar FMT
+.It Fl \-related Pq Fl r
+.It Fl \-related-all
+.It Fl \-revalued
+.It Fl \-revalued-only
+.It Fl \-revalued-total Ar EXPR
+.It Fl \-seed Ar INT
+.It Fl \-script
+.It Fl \-set-account Ar EXPR
+.It Fl \-set-payee Ar EXPR
+.It Fl \-set-price Ar EXPR
+.It Fl \-sort Ar EXPR Pq Fl S
+.It Fl \-sort-all
+.It Fl \-sort-xacts
+.It Fl \-start-of-week Ar STR
+.It Fl \-strict
+.It Fl \-subtotal Pq Fl s
+.It Fl \-tail Ar INT
+.It Fl \-total Ar EXPR
+.It Fl \-total-data Pq Fl J
+.It Fl \-total-width Ar INT
+.It Fl \-trace Ar INT
+.It Fl \-truncate
+.It Fl \-unbudgeted
+.It Fl \-uncleared Pq Fl U
+.It Fl \-unround
+.It Fl \-verbose
+.It Fl \-verify
+.It Fl \-version
+.It Fl \-weekly Pq Fl W
+.It Fl \-wide Pq Fl w
+.It Fl \-yearly Pq Fl Y
+.El
+.Pp
+.Sh PRECOMMANDS
+.Pp
+.Bl -tag -width -indent
+.It Nm args
+.It Nm eval
+.It Nm format
+.It Nm parse
+.It Nm period
+.It Nm python
+.It Nm template
+.El
+.Pp
+.Sh QUERIES
+The syntax for reporting queries can get somewhat complex. It is a series of
+query terms with an implicit OR operator between them. The following terms
+are accepted:
+.Bl -tag -width "term and term"
+.It Ar regex
+A bare string is taken as a regular expression matching the full account name.
+Thus, to report the current balance for all assets and liabilities, you would
+use:
+.Pp
+.Dl ledger bal asset liab
+.It Nm payee Ar regex Pq \&@ Ns Ar regex
+Query on the payee, rather than the account.
+.It Nm tag Ar regex Pq \&% Ns Ar regex
+.It Nm note Ar regex Pq \&= Ns Ar regex
+Query on anything found in an item's note.
+.It Nm code Ar regex Pq \&# Ns Ar regex
+Query on the xact's optional code (which can be any string the user wishes).
+.It Ar term Nm and Ar term
+Query terms are joined by an implicit OR operator. You can change this to AND
+by using that keyword. For example, to show food expenditures occurring at
+Shakee's Pizza, you could say:
+.Pp
+.Dl ledger reg food and @Shakee
+.It Ar term Nm or Ar term
+When you wish to be more explicit, use the OR operator.
+.It Nm show
+.It Nm not Ar term
+Reverse the logical meaning of the following term. This can be used with
+parentheses to great effect:
+.Pp
+.Dl ledger reg food and @Shakee and not dining
+.It \&( Ar term No \&)
+If you wish to mix OR and AND operators, it is often helpful to surround
+logical units with parentheses. \fBNOTE\fR: Because of the way some shells
+interpret parentheses, you should always escape them:
+.Pp
+.Dl ledger bal \e\\\&( assets or liab \e\\\&) and not food
+.El
+.Pp
+.Sh EXPRESSIONS
+.Bl -tag -width "partial_account"
+.It Nm account
+.It Nm account_base
+.It Nm account_amount
+.It Nm actual
+.It Nm amount
+.It Nm amount_expr
+.It Fn ansify_if value color bool
+Render the given
+.Ar value
+as a string, applying the proper ANSI escape codes to display it in the given
+.Ar color
+if
+.Ar bool
+is true. It typically checks the value of the option
+.Nm Fl \-color ,
+for example:
+.Dl ansify_if(amount, "blue", options.color)
+.It Nm beg_line
+.It Nm beg_pos
+.It Nm calculated
+.It Nm cleared
+.It Nm code
+.It Nm comment
+.It Nm commodity
+.It Nm cost
+.It Nm count
+.It Nm date
+.It Nm depth
+.It Nm depth_spacer
+.It Nm display_amount
+.It Nm display_total
+.It Nm end_line
+.It Nm end_pos
+.It Nm filename
+.It Nm format_date
+.It Nm get_at
+.It Nm has_meta
+.It Nm has_tag
+.It Nm is_seq
+.It Nm join
+.It Nm market
+.It Nm meta
+.It Nm note
+.It Nm null
+.It Nm options
+.It Nm partial_account
+.It Nm payee
+.It Nm pending
+.It Nm post
+.It Nm print
+.It Nm quantity
+.It Nm quoted
+.It Nm real
+.It Nm rounded
+.It Nm scrub
+.It Nm status
+.It Nm strip
+.It Nm subcount
+.It Nm tag
+.It Nm today
+.It Nm total
+.It Nm total_expr
+.It Nm truncate
+.It Nm uncleared
+.It Nm virtual
+.It Nm xact
+.El
+.Pp
+.Sh DRAFTS
+.Pp
+.Sh FORMATS
+.Pp
+.Sh DEBUG COMMANDS
+In addition to the regular reporting commands, Ledger also accepts several
+debug commands:
+.Bl -tag -width balance
+.It Nm args Oo Ar report-query Oc
+Accepts a
+.Ar report-query
+as its argument and displays it back to the user along with a complete
+analysis of how Ledger interpreted it. Useful if you want to understand how
+report queries are translated into value expressions.
+.It Nm eval Oo Ar value-expression Oc
+Evaluates the given
+.Ar value-expression
+and prints the result. For more on value expressions, see the section
+.Sx EXPRESSIONS .
+.It Nm format Oo Ar format-string Oc
+Accepts a
+.Ar format-string
+and displays an analysis of how it was parsed, and what it would look like
+applied to a sample transaction. For more on format strings, see the section
+.Sx FORMATS .
+.It Nm generate
+Generates 50 randomly composed yet valid Ledger transactions.
+.It Nm parse Oo Ar value-expression Oc
+Parses the given
+.Ar value-expression
+and display an analysis of the expression tree and its evaluated value. For
+more on value expressions, see the section
+.Sx EXPRESSIONS .
+.It Nm python Oo Ar file Oc
+Invokes a Python interpreter to read the given
+.Ar file .
+What is special about this is that the ledger module is builtin, not read from
+disk, so it doesn't require Ledger to be installed anywhere, or the shared
+library variants to be built.
+.It Nm reload
+Used only in the
+.Tn REPL ,
+it causes an immediate reloading of all data files for the current session.
+.It Nm template Oo Ar draft-template Oc
+Accepts a
+.Ar draft-template
+and displays information about how it was parsed. See the section on
+.Sx DRAFTS .
+.El
+.Pp
+.Sh SEE ALSO
+.Xr beancount 1,
+.Xr hledger 1
+.Sh AUTHORS
+.An "John Wiegley"
+.Aq johnw@newartisans.com
+.\" .Sh BUGS \" Document known, unremedied bugs
+.\" .Sh HISTORY \" Document history if command behaves in a unique manner
diff --git a/ledger.texi b/doc/ledger.texi
index 4b995e78..3b0785eb 100644
--- a/ledger.texi
+++ b/doc/ledger.texi
@@ -5,7 +5,7 @@
@dircategory User Applications
@copying
-Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+Copyright (c) 2003-2009, John Wiegley. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -61,12 +61,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@menu
* Introduction::
-* Running Ledger::
-* Keeping a ledger::
-* Using XML::
+* Quick Reference::
+* Ledger Tutorial::
+* Ledger in Practice::
@end menu
-@node Introduction, Running Ledger, Top, Top
+@ifnottex
+@section Copyright
+@insertcopying
+@end ifnottex
+
+@node Introduction, Quick Reference, Top, Top
@chapter Introduction
Ledger is an accounting tool with the moxie to exist. It provides no
@@ -90,7 +95,7 @@ company's name. The ultimate aim of keeping a checkbook ledger is to
know how much money is available to spend. That's really the aim of
all ledgers.
-What computers add is the ability to walk through these transactions,
+What computers add is the ability to walk through these postings,
and tell you things about your spending habits; to let you devise
budgets and get control over your spending; to squirrel away money
into virtual savings account without having to physically move money
@@ -104,7 +109,7 @@ of all your accounts, not just checking. In such a ledger, you record
not only who gets paid---in the case of a debit---but where the money
came from. In a checkbook ledger, its assumed that all the money
comes from your checking account. But in a general ledger, you write
-transaction two-lines: the source account and target account.
+posting two-lines: the source account and target account.
@emph{There must always be a debit from at least one account for every
credit made to another account}. This is what is meant by
``double-entry'' accounting: the ledger must always balance to zero,
@@ -117,7 +122,7 @@ general ledger you need to record a payment to Pacific Bell for your
monthly phone bill. The cost is $23.00, let's say, and you want to
pay it from your checking account. In the general ledger you need to
say where the money came from, in addition to where it's going to.
-The entry might look like this:
+The transaction might look like this:
@smallexample
9/29 BAL Pacific Bell $-200.00 $-200.00
@@ -132,17 +137,17 @@ The first line shows a payment to Pacific Bell for $23.00. Because
there is no ``balance'' in a general ledger---it's always zero---we
write in the total balance of all payments to ``Pacific Bell'', which
now is $223.00 (previously the balance was $200.00). This is done by
-looking at the last entry for ``Pacific Bell'' in the ledger, adding
+looking at the last transaction for ``Pacific Bell'' in the ledger, adding
$23.00 to that amount, and writing the total in the balance column.
And the money came from ``Checking''---a withdrawal of $23.00---which
leaves the ending balance in ``Checking'' at $77.00. This is a very
manual procedure; but that's where computers come in...
-The transaction must balance to $0: $23 went to Pacific Bell, $23 came
+The posting must balance to $0: $23 went to Pacific Bell, $23 came
from Checking. There is nothing left over to be accounted for, since
the money has simply moved from one account to another. This is the
basis of double-entry accounting: that money never pops in or out of
-existence; it is always a transaction from one account to another.
+existence; it is always a posting from one account to another.
Keeping a general ledger is the same as keeping two separate ledgers:
One for Pacific Bell and one for Checking. In that case, each time a
@@ -155,16 +160,16 @@ deal with multiple accounts.
Enter the beauty of computerized accounting. The purpose of the
Ledger program is to make general ledger accounting simple, by keeping
track of the balances for you. Your only job is to enter the
-transactions. If a transaction does not balance, Ledger displays an
-error and indicates the incorrect transaction.@footnote{In some
-special cases, it automatically balances this entry for you.}
+postings. If a posting does not balance, Ledger displays an
+error and indicates the incorrect posting.@footnote{In some
+special cases, it automatically balances this transaction for you.}
In summary, there are two aspects of Ledger use: updating the ledger
data file, and using the Ledger tool to view the summarized result of
-your entries.
+your transactions.
And just for the sake of example---as a starting point for those who
-want to dive in head-first---here are the ledger entries from above,
+want to dive in head-first---here are the ledger transactions from above,
formatting as the ledger program wishes to see them:
@smallexample
@@ -190,12 +195,59 @@ $ ledger -f ledger.dat register checking
$ ledger -f ledger.dat register bell
@end example
-@menu
-* Building the program::
-* Getting help::
-@end menu
+@section More introduction
+
+The most important part of accounting is keeping a good ledger. If
+you have a good ledger, tools can be written to work whatever
+mathematically tricks you need to better understand your spending
+patterns. Without a good ledger, no tool, however smart, can help
+you.
+
+The Ledger program aims at making ledger transaction as simple as possible.
+Since it is a command-line tool, it does not provide a user interface
+for keeping a ledger. If you like, you may use GnuCash to maintain
+your ledger, in which case the Ledger program will read GnuCash's data
+files directly. In that case, read the GnuCash manual now, and skip
+to the next chapter.
+
+If you are not using GnuCash, but a text editor to maintain your
+ledger, read on. Ledger has been designed to make data transaction as
+simple as possible, by keeping the ledger format easy, and also by
+automagically determining as much information as possible based on the
+nature of your transactions.
+
+For example, you do not need to tell Ledger about the accounts you
+use. Any time Ledger sees a posting involving an account it knows
+nothing about, it will create it. If you use a commodity that is new
+to Ledger, it will create that commodity, and determine its display
+characteristics (placement of the symbol before or after the amount,
+display precision, etc) based on how you used the commodity in the
+posting.
+
+Here is the Pacific Bell example from above, given as a Ledger
+posting:
+
+@smallexample
+9/29 (100) Pacific Bell
+ Expenses:Utilities:Phone $23.00
+ Assets:Checking $-23.00
+@end smallexample
+
+As you can see, it is very similar to what would be written on paper,
+minus the computed balance totals, and adding in account names that
+work better with Ledger's scheme of things. In fact, since Ledger is
+smart about many things, you don't need to specify the balanced
+amount, if it is the same as the first line:
+
+@smallexample
+9/29 (100) Pacific Bell
+ Expenses:Utilities:Phone $23.00
+ Assets:Checking
+@end smallexample
+
+For this transaction, Ledger will figure out that $-23.00 must come from
+@samp{Assets:Checking} in order to balance the transaction.
-@node Building the program, Getting help, Introduction, Introduction
@section Building the program
Ledger is written in ANSI C++, and should compile on any platform. It
@@ -210,7 +262,6 @@ enter these commands:
./configure && make install
@end example
-@node Getting help, , Building the program, Introduction
@section Getting help
If you need help on how to use Ledger, or run into problems, you can
@@ -223,8 +274,12 @@ https://lists.sourceforge.net/lists/listinfo/ledger-discuss
You can also find help at the @samp{#ledger} channel on the IRC server
@samp{irc.freenode.net}.
-@node Running Ledger, Keeping a ledger, Introduction, Top
-@chapter Running Ledger
+@node Quick Reference, Ledger Tutorial, Introduction, Top
+@chapter Quick Reference
+
+This chapter describes ledger's features and serves as a quick
+reference. You may wish to survey this to get an overview before diving
+in to the @ref{Ledger Tutorial} and more detailed examples that follow.
Ledger has a very simple command-line interface, named---enticing
enough---@command{ledger}. It supports a few reporting commands, and
@@ -238,12 +293,12 @@ ledger [OPTIONS...] COMMAND [ARGS...]
Command options must always precede the command word. After the
command word there may appear any number of arguments. For most
commands, these arguments are regular expressions that cause the
-output to relate only to transactions matching those regular
-expressions. For the @command{entry} command, the arguments have a
+output to relate only to postings matching those regular
+expressions. For the @command{transaction} command, the arguments have a
special meaning, described below.
The regular expressions arguments always match the account name that a
-transaction refers to. To match on the payee of the entry instead,
+posting refers to. To match on the payee of the transaction instead,
precede the regular expression with @samp{--}. For example, the
following balance command reports account totals for rent, food and
movies, but only those whose payee matches Freddie:
@@ -258,24 +313,1117 @@ However, none of them are required to use the basic reporting
commands.
@menu
-* Usage overview::
* Commands::
* Options::
+* Period expressions::
* Format strings::
* Value expressions::
-* Period expressions::
* File format::
-* Some typical queries::
-* Budgeting and forecasting::
@end menu
-@node Usage overview, Commands, Running Ledger, Running Ledger
-@section Usage overview
+@node Commands, Options, Quick Reference, Quick Reference
+@section Commands
+
+@subsection balance
+
+The @command{balance} command reports the current balance of all
+accounts. It accepts a list of optional regexps, which confine the
+balance report to the matching accounts. If an account contains
+multiple types of commodities, each commodity's total is reported
+separately.
+
+@subsection register
+
+The @command{register} command displays all the postings occurring
+in a single account, line by line. The account regexp must be
+specified as the only argument to this command. If any regexps occur
+after the required account name, the register will contain only those
+postings that match. Very useful for hunting down a particular
+posting.
+
+The output from @command{register} is very close to what a typical
+checkbook, or single-account ledger, would look like. It also shows a
+running balance. The final running balance of any register should
+always be the same as the current balance of that account.
+
+If you have Gnuplot installed, you may plot the amount or running
+total of any register by using the script @file{report}, which is
+included in the Ledger distribution. The only requirement is that you
+add either @option{-j} or @option{-J} to your register command, in
+order to plot either the amount or total column, respectively.
+
+@subsection print
+
+The @command{print} command prints out ledger transactions in a textual
+format that can be parsed by Ledger. They will be properly formatted,
+and output in the most economic form possible. The ``print'' command
+also takes a list of optional regexps, which will cause only those
+postings which match in some way to be printed.
+
+The @command{print} command can be a handy way to clean up a ledger
+file whose formatting has gotten out of hand.
+
+@subsection output
+
+The @command{output} command is very similar to the @command{print}
+command, except that it attempts to replicate the specified ledger
+file epostly. The format of the command is:
+
+@example
+ledger -f FILENAME output FILENAME
+@end example
+
+Where @file{FILENAME} is the name of the ledger file to output. The
+reason for specifying this command is that only transactions contained
+within that file will be output, and not an included transactions (as can
+happen with the @command{print} command).
+
+@subsection xml
+
+The @command{xml} command outputs results similar to what
+@command{print} and @command{register} display, but as an XML form.
+This data can then be read in and processed. Use the
+@option{--totals} option to include the running total with each
+posting.
+
+@subsection emacs
+
+The @command{emacs} command outputs results in a form that can be read
+directly by Emacs Lisp. The format of the sexp is:
+
+@example
+((BEG-POS CLEARED DATE CODE PAYEE
+ (ACCOUNT AMOUNT)...) ; list of postings
+ ...) ; list of transactions
+@end example
+
+@subsection equity
+
+The @command{equity} command prints out accounts balances as if they
+were transactions. This makes it easy to establish the starting balances
+for an account, such as when @ref{Archiving previous years}.
+
+@subsection prices
+
+The @command{prices} command displays the price history for matching
+commodities. The @option{-A} flag is useful with this report, to
+display the running average price, or @option{-D} to show each price's
+deviation from that average.
+
+There is also a @command{pricesdb} command which outputs the same
+information as @command{prices}, but does in a format that can be
+parsed by Ledger.
+
+@subsection xact
+
+The @command{xact} commands simplifies the creation of new transactions.
+It works on the principle that 80% of all postings are variants of
+earlier postings. Here's how it works:
+
+Say you currently have this posting in your ledger file:
+
+@smallexample
+2004/03/15 * Viva Italiano
+ Expenses:Food $12.45
+ Expenses:Tips $2.55
+ Liabilities:MasterCard $-15.00
+@end smallexample
+
+Now it's @samp{2004/4/9}, and you've just eating at @samp{Viva
+Italiano} again. The epost amounts are different, but the overall
+form is the same. With the @command{xact} command you can type:
+
+@example
+ledger xact 2004/4/9 viva food 11 tips 2.50
+@end example
+
+This produces the following output:
+
+@smallexample
+2004/04/09 Viva Italiano
+ Expenses:Food $11.00
+ Expenses:Tips $2.50
+ Liabilities:MasterCard $-13.50
+@end smallexample
+
+It works by finding a past posting matching the regular expression
+@samp{viva}, and assuming that any accounts or amounts specified will
+be similar to that earlier posting. If Ledger does not succeed in
+generating a new transaction, an error is printed and the exit code is set
+to @samp{1}.
+
+There is a shell script in the distribution's @file{scripts} directory
+called @file{xact}, which simplifies the task of adding a new transaction
+to your ledger. It launches @command{vi} to confirm that the transaction
+looks appropriate.
+
+Here are a few more examples of the @command{xact} command, assuming
+the above journal transaction:
+
+@example
+ledger xact 4/9 viva 11.50
+ledger xact 4/9 viva 11.50 checking # (from `checking')
+ledger xact 4/9 viva food 11.50 tips 8
+ledger xact 4/9 viva food 11.50 tips 8 cash
+ledger xact 4/9 viva food $11.50 tips $8 cash
+ledger xact 4/9 viva dining "DM 11.50"
+@end example
+
+@node Options, Period expressions, Commands, Quick Reference
+@section Options
+
+With all of the reports, command-line options are useful to modify the
+output generated. These command-line options always occur before the
+command word. This is done to distinguish options from exclusive
+regular expressions, which also begin with a dash. The basic form for
+most commands is:
+
+@example
+ledger [OPTIONS] COMMAND [REGEXPS...] [-- [REGEXPS...]]
+@end example
+
+The @var{OPTIONS} and @var{REGEXPS} expressions are both optional.
+You could just use @samp{ledger balance}, without any options---which
+prints a summary of all accounts. But for more specific reporting, or
+to change the appearance of the output, options are needed.
+
+@subsection Basic options
+
+These are the most basic command options. Most likely, the user will
+want to set them using environment variables (see @ref{Options}),
+instead of using actual command-line options:
+
+@option{--help} (@option{-h}) prints a summary of all the options, and
+what they are used for. This can be a handy way to remember which
+options do what. This help screen is also printed if ledger is run
+without a command.
+
+@option{--version} (@option{-v}) prints the current version of ledger
+and exits. This is useful for sending bug reports, to let the author
+know which version of ledger you are using.
+
+@option{--file FILE} (@option{-f FILE}) reads FILE as a ledger file.
+This command may be used multiple times. FILE may also be a list of
+file names separated by colons. Typically, the environment variable
+@env{LEDGER_FILE} is set, rather than using this command-line option.
+
+@option{--output FILE} (@option{-o FILE}) redirects output from any
+command to @var{FILE}. By default, all output goes to standard
+output.
+
+@option{--init-file FILE} (@option{-i FILE}) causes FILE to be read by
+ledger before any other ledger file. This file may not contain any
+postings, but it may contain option settings. To specify options
+in the init file, use the same syntax as the command-line. Here's an
+example init file:
+
+@smallexample
+--price-db ~/finance/.pricedb
+
+; ~/.ledgerrc ends here
+@end smallexample
+
+Option settings on the command-line or in the environment always take
+precedence over settings in the init file.
+
+@option{--cache FILE} identifies FILE as the default binary cache
+file. That is, if the ledger files to be read are specified using the
+environment variable @env{LEDGER_FILE}, then whenever a command is
+finished a binary copy will be written to the specified cache, to
+speed up the loading time of subsequent queries. This filename can
+also be given using the environment variable @env{LEDGER_CACHE}, or by
+putting the option into your init file. The @option{--no-cache}
+option causes Ledger to always ignore the binary cache.
+
+@option{--account NAME} (@option{-a NAME}) specifies the default
+account which QIF file postings are assumed to relate to.
+
+@subsection Report filtering
+
+These options change which postings affect the outcome of a
+report, in ways other than just using regular expressions:
+
+@option{--current}(@option{-c}) displays only transactions occurring on or
+before the current date.
+
+@option{--begin DATE} (@option{-b DATE}) constrains the report to
+transactions on or after @var{DATE}. Only transactions after that date will be
+calculated, which means that the running total in the balance report
+will always start at zero with the first matching transaction. (Note: This
+is different from using @option{--display} to constrain what is
+displayed).
+
+@option{--end DATE} (@option{-e DATE}) constrains the report so that
+transactions on or after @var{DATE} are not considered. The ending date
+is inclusive.
+
+@option{--period STR} (@option{-p STR}) sets the reporting period
+to @var{STR}. This will subtotal all matching transactions within each
+period separately, making it easy to see weekly, monthly, quarterly,
+etc., posting totals. A period string can even specify the
+beginning and end of the report range, using simple terms like ``last
+june'' or ``next month''. For more using period expressions, see
+@ref{Period expressions}.
+
+@option{--period-sort EXPR} sorts the postings within each
+reporting period using the value expression @var{EXPR}. This is most
+often useful when reporting monthly expenses, in order to view the
+highest expense categories at the top of each month:
+
+@example
+ledger -M --period-sort -At reg ^Expenses
+@end example
+
+@option{--cleared} (@option{-C}) displays only postings whose transaction
+has been marked ``cleared'' (by placing an asterix to the right of the
+date).
+
+@option{--uncleared} (@option{-U}) displays only postings whose
+transaction has not been marked ``cleared'' (i.e., if there is no asterix to
+the right of the date).
+
+@option{--real} (@option{-R}) displays only real postings, not
+virtual. (A virtual posting is indicated by surrounding the
+account name with parentheses or brackets; see the section on using
+virtual postings for more information).
+
+@option{--actual} (@option{-L}) displays only actual postings, and
+not those created due to automated postings.
+
+@option{--related} (@option{-r}) displays postings that are
+related to whichever postings would otherwise have matched the
+filtering criteria. In the register report, this shows where money
+went to, or the account it came from. In the balance report, it shows
+all the accounts affected by transactions having a related posting.
+For example, if a file had this transaction:
+
+@smallexample
+2004/03/20 Safeway
+ Expenses:Food $65.00
+ Expenses:Cash $20.00
+ Assets:Checking $-85.00
+@end smallexample
+
+And the register command was:
+
+@example
+ledger -r register food
+@end example
+
+The following would be output, showing the postings related to the
+posting that matched:
+
+@smallexample
+2004/03/20 Safeway Expenses:Cash $-20.00 $-20.00
+ Assets:Checking $85.00 $65.00
+@end smallexample
+
+@option{--budget} is useful for displaying how close your postings
+meet your budget. @option{--add-budget} also shows unbudgeted
+postings, while @option{--unbudgeted} shows only those.
+@option{--forecast} is a related option that projects your budget into
+the future, showing how it will affect future balances.
+@xref{Budgeting and forecasting}.
+
+@option{--limit EXPR} (@option{-l EXPR}) limits which postings
+take part in the calculations of a report.
+
+@option{--amount EXPR} (@option{-t EXPR}) changes the value expression
+used to calculate the ``value'' column in the @command{register}
+report, the amount used to calculate account totals in the
+@command{balance} report, and the values printed in the
+@command{equity} report. @xref{Value expressions}.
+
+@option{--total EXPR} (@option{-T EXPR}) sets the value expression
+used for the ``totals'' column in the @command{register} and
+@command{balance} reports.
+
+@subsection Output customization
+
+These options affect only the output, but not which postings are
+used to create it:
+
+@option{--collapse} (@option{-n}) causes transactions in a
+@command{register} report with multiple postings to be collapsed
+into a single, subtotaled transaction.
+
+@option{--subtotal} (@option{-s}) causes all transactions in a
+@command{register} report to be collapsed into a single, subtotaled
+transaction.
+
+@option{--by-payee} (@option{-P}) reports subtotals by payee.
+
+@option{--comm-as-payee} (@option{-x}) changes the payee of every
+posting to be the commodity used in that posting. This can be
+useful when combined with other options, such as @option{-s}.
+
+@option{--empty} (@option{-E}) includes even empty accounts in the
+@command{balance} report.
+
+@option{--weekly} (@option{-W}) reports posting totals by the
+week. The week begins on whichever day of the week begins the month
+containing that posting. To set a specific begin date, use a
+period string, such as @samp{weekly from DATE}. @option{--monthly}
+(@option{-M}) reports posting totals by month; @option{--yearly}
+(@option{-Y}) reports posting totals by year. For more complex
+period, using the @option{--period} option described above.
+
+@option{--dow} reports postings totals for each day of the week.
+This is an easy way to see if weekend spending is more than on
+weekdays.
+
+@option{--sort EXPR} (@option{-S EXPR}) sorts a report by comparing
+the values determined using the value expression @var{EXPR}. For
+example, using @option{-S -UT} in the balance report will sort account
+balances from greatest to least, using the absolute value of the
+total. For more on how to use value expressions, see @ref{Value
+expressions}.
+
+@option{--wide} (@option{-w}) causes the default @command{register}
+report to assume 132 columns instead of 80.
+
+@option{--head} causes only the first N transactions to be printed. This
+is different from using the command-line utility @command{head}, which
+would limit to the first N postings. @option{--tail} outputs only
+the last N transactions. Both options may be used simultaneously. If a
+negative amount is given, it will invert the meaning of the flag
+(instead of the first five transactions being printed, for example, it
+would print all but the first five).
+
+@option{--pager} tells Ledger to pass its output to the given pager
+program---very useful when the output is especially long. This
+behavior can be made the default by setting the @env{LEDGER_PAGER}
+environment variable.
+
+@option{--average} (@option{-A}) reports the average posting
+value.
+
+@option{--deviation} (@option{-D}) reports each posting's
+deviation from the average. It is only meaningful in the
+@command{register} and @command{prices} reports.
+
+@option{--percentage} (@option{-%}) shows account subtotals in the
+@command{balance} report as percentages of the parent account.
+
+@option{--totals} include running total information in the
+@command{xml} report.
+
+@option{--amount-data} (@option{-j}) changes the @command{register}
+report so that it output nothing but the date and the value column,
+and the latter without commodities. This is only meaningful if the
+report uses a single commodity. This data can then be fed to other
+programs, which could plot the date, analyze it, etc.
+
+@option{--total-data} (@option{-J}) changes the @command{register}
+report so that it output nothing but the date and totals column,
+without commodities.
+
+@option{--display EXPR} (@option{-d EXPR}) limits which postings
+or accounts or actually displayed in a report. They might still be
+calculated, and be part of the running total of a register report, for
+example, but they will not be displayed. This is useful for seeing
+last month's checking postings, against a running balance which
+includes all posting values:
+
+@example
+ledger -d "d>=[last month]" reg checking
+@end example
+
+The output from this command is very different from the following,
+whose running total includes only postings from the last month
+onward:
+
+@example
+ledger -p "last month" reg checking
+@end example
+
+Which is more useful depends on what you're looking to know: the total
+amount for the reporting range (@option{-p}), or simply a display
+restricted to the reporting range (using @option{-d}).
+
+@option{--date-format STR} (@option{-y STR}) changes the basic date
+format used by reports. The default uses a date like 2004/08/01,
+which represents the default date format of @samp{%Y/%m/%d}. To
+change the way dates are printed in general, the easiest way is to put
+@option{--date-format FORMAT} in the Ledger initialization file
+@file{~/.ledgerrc} (or the file referred to by @env{LEDGER_INIT}).
+
+@option{--format STR} (@option{-F STR}) sets the reporting format for
+whatever report ledger is about to make. @xref{Format strings}.
+There are also specific format commands for each report type:
+
+@itemize
+@item @option{--balance-format STR}
+@item @option{--register-format STR}
+@item @option{--print-format STR}
+@item @option{--plot-amount-format STR} (-j @command{register})
+@item @option{--plot-total-format STR} (-J @command{register})
+@item @option{--equity-format STR}
+@item @option{--prices-format STR}
+@item @option{--wide-register-format STR} (-w @command{register})
+@end itemize
+
+@subsection Commodity reporting
+
+These options affect how commodity values are displayed:
+
+@option{--price-db FILE} sets the file that is used for recording
+downloaded commodity prices. It is always read on startup, to
+determine historical prices. Other settings can be placed in this
+file manually, to prevent downloading quotes for a specific, for
+example. This is done by adding a line like the following:
+
+@example
+; Don't download quotes for the dollar, or timelog values
+N $
+N h
+@end example
+
+@option{--price-exp MINS} (@option{-L MINS}) sets the expected
+freshness of price quotes, in minutes. That is, if the last known
+quote for any commodity is older than this value---and if
+@option{--download} is being used---then the Internet will be
+consulted again for a newer price. Otherwise, the old price is still
+considered to be fresh enough.
+
+@option{--download} (@option{-Q}) causes quotes to be automagically
+downloaded, as needed, by running a script named @command{getquote}
+and expecting that script to return a value understood by ledger. A
+sample implementation of a @command{getquote} script, implemented in
+Perl, is provided in the distribution. Downloaded quote price are
+then appended to the price database, usually specified using the
+environment variable @env{LEDGER_PRICE_DB}.
+
+There are several different ways that ledger can report the totals it
+displays. The most flexible way to adjust them is by using value
+expressions, and the @option{-t} and @option{-T} options. However,
+there are also several ``default'' reports, which will satisfy most
+users basic reporting needs:
+
+@table @code
+@item -O, --quantity
+Reports commodity totals (this is the default)
+
+@item -B, --basis
+Reports the cost basis for all postings.
+
+@item -V, --market
+Reports the last known market value for all commodities.
+
+@item -G --gain
+Reports the net gain/loss for all commodities in the report that have
+a price history.
+@end table
+
+@subsection Environment variables
+
+Every option to ledger may be set using an environment variable. If
+an option has a long name such @option{--this-option}, setting the
+environment variable @env{LEDGER_THIS_OPTION} will have the same
+affect as specifying that option on the command-line. Options on the
+command-line always take precedence over environment variable
+settings, however.
+
+Note that you may also permanently specify option values by placing
+option settings in the file @file{~/.ledgerrc}, for example:
+
+@example
+--cache /tmp/.mycache
+@end example
+
+@node Period expressions, Format strings, Options, Quick Reference
+@section Period expressions
+
+A period expression indicates a span of time, or a reporting interval,
+or both. The full syntax is:
+
+@example
+[INTERVAL] [BEGIN] [END]
+@end example
+
+The optional @var{INTERVAL} part may be any one of:
+
+@example
+every day
+every week
+every monthly
+every quarter
+every year
+every N days # N is any integer
+every N weeks
+every N months
+every N quarters
+every N years
+daily
+weekly
+biweekly
+monthly
+bimonthly
+quarterly
+yearly
+@end example
+
+After the interval, a begin time, end time, both or neither may be
+specified. As for the begin time, it can be either of:
+
+@example
+from <SPEC>
+since <SPEC>
+@end example
+
+The end time can be either of:
+
+@example
+to <SPEC>
+until <SPEC>
+@end example
+
+Where @var{SPEC} can be any of:
+
+@example
+2004
+2004/10
+2004/10/1
+10/1
+october
+oct
+this week # or day, month, quarter, year
+next week
+last week
+@end example
+
+The beginning and ending can be given at the same time, if it spans a
+single period. In that case, just use @var{SPEC} by itself. In that
+case, the period @samp{oct}, for example, will cover all the days in
+october. The possible forms are:
+
+@example
+<SPEC>
+in <SPEC>
+@end example
+
+Here are a few examples of period expressions:
+
+@example
+monthly
+monthly in 2004
+weekly from oct
+weekly from last month
+from sep to oct
+from 10/1 to 10/5
+monthly until 2005
+from apr
+until nov
+last oct
+weekly last august
+@end example
+
+@node Format strings, Value expressions, Period expressions, Quick Reference
+@section Format strings
+
+Format strings may be used to change the output format of reports.
+They are specified by passing a formatting string to the
+@option{--format} (@option{-F}) option. Within that string,
+constructs are allowed which make it possible to display the various
+parts of an account or posting in custom ways.
+
+Within a format strings, a substitution is specified using a percent
+character (@samp{%}). The basic format of all substitutions is:
+
+@example
+%[-][MIN WIDTH][.MAX WIDTH]EXPR
+@end example
+
+If the optional minus sign (@samp{-}) follows the percent character,
+whatever is substituted will be left justified. The default is right
+justified. If a minimum width is given next, the substituted text
+will be at least that wide, perhaps wider. If a period and a maximum
+width is given, the substituted text will never be wider than this,
+and will be truncated to fit. Here are some examples:
+
+@example
+%-P a transaction's payee, left justified
+%20P The same, right justified, at least 20 chars wide
+%.20P The same, no more than 20 chars wide
+%-.20P Left justified, maximum twenty chars wide
+@end example
+
+The expression following the format constraints can be a single
+letter, or an expression enclosed in parentheses or brackets. The
+allowable expressions are:
+
+@table @code
+@item %
+Inserts a percent sign.
+
+@item t
+Inserts the results of the value expression specified by @option{-t}.
+If @option{-t} was not specified, the current report style's value
+expression is used.
+
+@item T
+Inserts the results of the value expression specified by @option{-T}.
+If @option{-T} was not specified, the current report style's value
+expression is used.
+
+@item |
+Inserts a single space. This is useful if a width is specified, for
+inserting a certain number of spaces.
+
+@item _
+Inserts a space for each level of an account's depth. That is, if an
+account has two parents, this construct will insert two spaces. If a
+minimum width is specified, that much space is inserted for each level
+of depth. Thus @samp{%5_}, for an account with four parents, will
+insert twenty spaces.
+
+@item (EXPR)
+Inserts the amount resulting from the value expression given in
+parentheses. To insert five times the total value of an account, for
+example, one could say @samp{%12(5*O)}. Note: It's important to put
+the five first in that expression, so that the commodity doesn't get
+stripped from the total.
+
+@item [DATEFMT]
+Inserts the result of formatting a posting's date with a date
+format string, epostly like those supported by @code{strftime}. For
+example: @samp{%[%Y/%m/%d %H:%M:%S]}.
+
+@item S
+Insert the pathname of the file from which the transaction's data was read.
+
+@item B
+Inserts the beginning character position of that transaction within the file.
+
+@item b
+Inserts the beginning line of that transaction within the file.
+
+@item E
+Inserts the ending character position of that transaction within the file.
+
+@item e
+Inserts the ending line of that transaction within the file.
+
+@item D
+By default, this is the same as @samp{%[%Y/%m%/d]}. The date format
+used can be changed at any time with the @option{-y} flag, however.
+Using @samp{%D} gives the user more control over the way dates are
+output.
+
+@item d
+This is the same as the @samp{%D} option, unless the transaction has an
+effective date, in which case it prints
+@samp{[ACTUAL_DATE=EFFECtIVE_DATE]}.
+
+@item X
+If a posting has been cleared, this inserts @samp{*} followed by a
+space; otherwise nothing is inserted.
+
+@item Y
+This is the same as @samp{%X}, except that it only displays a state
+character if all of the member postings have the same state.
+
+@item C
+Inserts the checking number for a transaction, in parentheses, followed by
+a space; if none was specified, nothing is inserted.
+
+@item P
+Inserts the payee related to a posting.
+
+@item a
+Inserts the optimal short name for an account. This is normally used
+in balance reports. It prints a parent account's name if that name
+has not been printed yet, otherwise it just prints the account's name.
+
+@item A
+Inserts the full name of an account.
+
+@item W
+This is the same as @samp{%A}, except that it first displays the
+posting's state @emph{if the transaction's posting states are not
+all the same}, followed by the full account name. This is offered as
+a printing optimization, so that combined with @samp{%Y}, only the
+minimum amount of state detail is printed.
+
+@item o
+Inserts the ``optimized'' form of a posting's amount. This is
+used by the print report. In some cases, this inserts nothing; in
+others, it inserts the posting amount and its cost. It's use is
+not recommend unless you are modifying the print report.
+
+@item n
+Inserts the note associated with a posting, preceded by two spaces
+and a semi-colon, if it exists. Thus, no none becomes an empty
+string, while the note @samp{foo} is substituted as @samp{ ; foo}.
+
+@item N
+Inserts the note associated with a posting, if one exists.
+
+@item /
+The @samp{%/} construct is special. It separates a format string
+between what is printed for the first posting of a transaction, and
+what is printed for all subsequent postings. If not used, the
+same format string is used for all postings.
+@end table
+
+@node Value expressions, File format, Format strings, Quick Reference
+@section Value expressions
+
+Value expressions are an expression language used by Ledger to
+calculate values used by the program for many different purposes:
+
+@enumerate
+@item
+The values displayed in reports
+@item
+For predicates (where truth is anything non-zero), to determine which
+postings are calculated (@option{-l}) or displayed (@option{-d}).
+@item
+For sorting criteria, to yield the sort key.
+@item
+In the matching criteria used by automated postings.
+@end enumerate
+
+Value expressions support most simple math and logic operators, in
+addition to a set of one letter functions and variables. A function's
+argument is whatever follows it. The following is a display predicate
+that I use with the @command{balance} command:
+
+@example
+ledger -d /^Liabilities/?T<0:UT>100 balance
+@end example
+
+The effect is that account totals are displayed only if: 1) A
+Liabilities account has a total less than zero; or 2) the absolute
+value of the account's total exceeds 100 units of whatever commodity
+contains. If it contains multiple commodities, only one of them must
+exceed 100 units.
+
+Display predicates are also very handy with register reports, to
+constrain which transactions are printed. For example, the following
+command shows only transactions from the beginning of the current month,
+while still calculating the running balance based on all transactions:
+
+@example
+ledger -d "d>[this month]" register checking
+@end example
+
+This advantage to this command's complexity is that it prints the
+running total in terms of all transactions in the register. The following,
+simpler command is similar, but totals only the displayed
+postings:
+
+@example
+ledger -b "this month" register checking
+@end example
+
+@subsection Variables
+
+Below are the one letter variables available in any value expression.
+For the register and print commands, these variables relate to
+individual postings, and sometimes the account affected by a
+posting. For the balance command, these variables relate to
+accounts---often with a subtle difference in meaning. The use of each
+variable for both is specified.
+
+@table @code
+@item t
+This maps to whatever the user specified with @option{-t}. In a
+register report, @option{-t} changes the value column; in a balance
+report, it has no meaning by default. If @option{-t} was not
+specified, the current report style's value expression is used.
+
+@item T
+This maps to whatever the user specified with @option{-T}. In a
+register report, @option{-T} changes the totals column; in a balance
+report, this is the value given for each account. If @option{-T} was
+not specified, the current report style's value expression is used.
+
+@item m
+This is always the present moment/date.
+@end table
+
+@subsubsection Posting/account details
+
+@table @code
+@item d
+A posting's date, as the number of seconds past the epoch. This
+is always ``today'' for an account.
+
+@item a
+The posting's amount; the balance of an account, without
+considering children.
+
+@item b
+The cost of a posting; the cost of an account, without its
+children.
+
+@item v
+The market value of a posting, or an account without its children.
+
+@item g
+The net gain (market value minus cost basis), for a posting or an
+account without its children. It is the same as @samp{v-b}.
+
+@item l
+The depth (``level'') of an account. If an account has one parent,
+it's depth is one.
+
+@item n
+The index of a posting, or the count of postings affecting an
+account.
+
+@item X
+1 if a posting's transaction has been cleared, 0 otherwise.
+
+@item R
+1 if a posting is not virtual, 0 otherwise.
+
+@item Z
+1 if a posting is not automated, 0 otherwise.
+@end table
+
+@subsubsection Calculated totals
+
+@table @code
+@item O
+The total of all postings seen so far, or the total of an account
+and all its children.
+
+@item N
+The total count of postings affecting an account and all its
+children.
+
+@item B
+The total cost of all postings seen so far; the total cost of an
+account and all its children.
+
+@item V
+The market value of all postings seen so far, or of an account and
+all its children.
+
+@item G
+The total net gain (market value minus cost basis), for a series of
+postings, or an account and its children. It is the same as
+@samp{V-B}.
+@end table
+
+@subsection Functions
+
+The available one letter functions are:
+
+@table @code
+@item -
+Negates the argument.
+
+@item U
+The absolute (unsigned) value of the argument.
+
+@item S
+Strips the commodity from the argument.
+
+@item A
+The arithmetic mean of the argument; @samp{Ax} is the same as
+@samp{x/n}.
+
+@item P
+The present market value of the argument. The syntax @samp{P(x,d)} is
+supported, which yields the market value at time @samp{d}. If no date
+is given, then the current moment is used.
+@end table
+
+@subsection Operators
+
+The binary and ternary operators, in order of precedence, are:
+
+@enumerate
+@item @samp{* /}
+@item @samp{+ -}
+@item @samp{! < > =}
+@item @samp{& | ?:}
+@end enumerate
+
+@subsection Complex expressions
+
+More complicated expressions are possible using:
+
+@table @code
+@item NUM
+A plain integer represents a commodity-less amount.
+
+@item @{AMOUNT@}
+An amount in braces can be any kind of amount supported by ledger,
+with or without a commodity. Use this for decimal values.
+
+@item /REGEXP/
+@item W/REGEXP/
+A regular expression that matches against an account's full name. If
+a posting, this will match against the account affected by the
+posting.
+
+@item //REGEXP/
+@item p/REGEXP/
+A regular expression that matches against a transaction's payee name.
+
+@item ///REGEXP/
+@item w/REGEXP/
+A regular expression that matches against an account's base name. If
+a posting, this will match against the account affected by the
+posting.
+
+@item c/REGEXP/
+A regular expression that matches against the transaction code (the text
+that occurs between parentheses before the payee name).
+
+@item e/REGEXP/
+A regular expression that matches against a posting's note, or
+comment field.
+
+@item (EXPR)
+A sub-expression is nested in parenthesis. This can be useful passing
+more complicated arguments to functions, or for overriding the natural
+precedence order of operators.
+
+@item [DATE]
+Useful specifying a date in plain terms. For example, you could say
+@samp{[2004/06/01]}.
+@end table
+
+@node File format, , Value expressions, Quick Reference
+@section File format
+
+The ledger file format is quite simple, but also very flexible. It
+supports many options, though typically the user can ignore most of
+them. They are summarized below.
+
+The initial character of each line determines what the line means, and
+how it should be interpreted. Allowable initial characters are:
+
+@table @code
+@item NUMBER
+A line beginning with a number denotes a transaction. It may be followed
+by any number of lines, each beginning with whitespace, to denote the
+transaction's account postings. The format of the first line is:
+
+@example
+DATE[=EDATE] [*|!] [(CODE)] DESC
+@end example
+
+If @samp{*} appears after the date (with optional effective date), it
+indicates the transaction is ``cleared'', which can mean whatever the user
+wants it t omean. If @samp{!} appears after the date, it indicates d
+the transaction is ``pending''; i.e., tentatively cleared from the user's
+point of view, but not yet actually cleared. If a @samp{CODE} appears
+in parentheses, it may be used to indicate a check number, or the type
+of the posting. Following these is the payee, or a description of
+the posting.
+
+The format of each following posting is:
+
+@example
+ ACCOUNT AMOUNT [; NOTE]
+@end example
+
+The @samp{ACCOUNT} may be surrounded by parentheses if it is a virtual
+postings, or square brackets if it is a virtual postings that
+must balance. The @samp{AMOUNT} can be followed by a per-unit
+posting cost, by specifying @samp{@@ AMOUNT}, or a complete
+posting cost with @samp{@@@@ AMOUNT}. Lastly, the @samp{NOTE} may
+specify an actual and/or effective date for the posting by using
+the syntax @samp{[ACTUAL_DATE]} or @samp{[=EFFECTIVE_DATE]} or
+@samp{[ACTUAL_DATE=EFFECtIVE_DATE]}.
+
+@item =
+An automated transaction. A value expression must appear after the equal
+sign.
+
+After this initial line there should be a set of one or more
+postings, just as if it were normal transaction. If the amounts of the
+postings have no commodity, they will be applied as modifiers to
+whichever real posting is matched by the value expression.
+
+@item ~
+A period transaction. A period expression must appear after the tilde.
+
+After this initial line there should be a set of one or more
+postings, just as if it were normal transaction.
+
+@item !
+A line beginning with an exclamation mark denotes a command directive.
+It must be immediately followed by the command word. The supported
+commands are:
+
+@table @samp
+@item !include
+Include the stated ledger file.
+
+@item !account
+The account name is given is taken to be the parent of all
+postings that follow, until @samp{!end} is seen.
+
+@item !end
+Ends an account block.
+@end table
+
+@item ;
+A line beginning with a colon indicates a comment, and is ignored.
+
+@item Y
+If a line begins with a capital Y, it denotes the year used for all
+subsequent transactions that give a date without a year. The year should
+appear immediately after the Y, for example: @samp{Y2004}. This is
+useful at the beginning of a file, to specify the year for that file.
+If all transactions specify a year, however, this command has no effect.
+
+@item P
+Specifies a historical price for a commodity. These are usually found
+in a pricing history file (see the @option{-Q} option). The syntax
+is:
+@example
+P DATE SYMBOL PRICE
+@end example
+
+@item N SYMBOL
+Indicates that pricing information is to be ignored for a given
+symbol, nor will quotes ever be downloaded for that symbol. Useful
+with a home currency, such as the dollar ($). It is recommended that
+these pricing options be set in the price database file, which
+defaults to @file{~/.pricedb}. The syntax for this command is:
+@example
+N SYMBOL
+@end example
+
+@item D AMOUNT
+Specifies the default commodity to use, by specifying an amount in the
+expected format. The @command{transaction} command will use this commodity
+as the default when none other can be determined. This command may be
+used multiple times, to set the default flags for different
+commodities; whichever is seen last is used as the default commodity.
+For example, to set US dollars as the default commodity, while also
+setting the thousands flag and decimal flag for that commodity, use:
+@example
+D $1,000.00
+@end example
-Before getting into the details of how to run Ledger, it will be
-easier to introduce the features in the context of their typical
-usage. To that end, this section presents a series of recipes,
-gradually introducing all of the command-line features of Ledger.
+@item C AMOUNT1 = AMOUNT2
+Specifies a commodity conversion, where the first amount is given to
+be equivalent to the second amount. The first amount should use the
+decimal precision desired during reporting:
+@example
+C 1.00 Kb = 1024 bytes
+@end example
+
+@item i, o, b, h
+These four relate to timeclock support, which permits ledger to read
+timelog files. See the timeclock's documentation for more info on the
+syntax of its timelog files.
+@end table
+
+@node Ledger Tutorial, Ledger in Practice, Quick Reference, Top
+@chapter Ledger Tutorial
+
+This chapter presents a series of recipes, gradually introducing all of
+the command-line features of Ledger.
For the purpose of these examples, assume the environment variable
@var{LEDGER} is set to the file @file{sample.dat} (which is included
@@ -315,7 +1463,7 @@ is recommended you follow: Keep all of your accounts under five parent
Assets, Liabilities, Income, Expenses and Equity. It is important to
do so in order to make sense out of the following examples.
-@subsection Checking balances
+@section Checking balances
Ledger has seven basic commands, but by far the most often used are
@command{balance} and @command{register}. To see a summary balance of
@@ -346,13 +1494,13 @@ We can see that in @samp{Assets} there is $1,480.00, and 50 shares of
Apple stock. There is also a negative grand total. Usually the grand
total is zero, which means that all accounts balance@footnote{It is
impossible for accounts not to balance in ledger; it reports an error
-if a transaction does not balance}. In this case, since the 50 shares
+if a posting does not balance}. In this case, since the 50 shares
of Apple stock cost $1,500.00 dollars, then these two amounts balance
each other in the grand total. The extra $2.00 comes from a virtual
-transaction being added by the automatic entry at the top of the file.
-The entry is virtual because the account name was surrounded by
-parentheses in an automatic entry. Automatic entries will be
-discussed later, but first let's remove the virtual transaction from
+posting being added by the automatic transaction at the top of the file.
+The transaction is virtual because the account name was surrounded by
+parentheses in an automatic transaction. Automatic transactions will be
+discussed later, but first let's remove the virtual posting from
the balance report by using the @option{--real} option:
@example
@@ -372,7 +1520,7 @@ Now the report is:
50 AAPL
@end smallexample
-Since the liability was a virtual transaction, it has dropped from the
+Since the liability was a virtual posting, it has dropped from the
report and we see that final total is balanced.
But we only know that it balances because @file{sample.dat} is quite
@@ -398,10 +1546,10 @@ With the basis cost option, the grand total has disappeared, as it is
now zero. The confirms that the cost of everything balances to zero,
@emph{which must always be true}. Reporting the real basis cost
should never yield a remainder@footnote{If it ever does, then
-generated transactions are involved, which can be removed using
+generated postings are involved, which can be removed using
@option{--actual}}.
-@subsubsection Sub-account balances
+@subsection Sub-account balances
The totals reported by the balance command are only the topmost parent
accounts. To see the totals of all child accounts as well, use the
@@ -456,7 +1604,7 @@ terse expression means: Display an account only if it has a non-zero
total (@code{T}), and its nesting level is less than or equal to 2
(@code{l<=2}).
-@subsubsection Specific account balances
+@subsection Specific account balances
While reporting the totals for all accounts can be useful, most often
you will want to check the balance of a specific account or accounts.
@@ -505,17 +1653,17 @@ Reports:
$-2.00 Liabilities:Taxes
@end smallexample
-@subsection The register report
+@section The register report
While the @command{balance} command can be very handy for checking
account totals, by far the most powerful of Ledger's reporting tools
is the @command{register} command. In fact, internally both commands
use the same logic, but report the results differently:
@command{balance} shows the summary totals, while @command{register}
-reports each transaction and how it contributes to that total.
+reports each posting and how it contributes to that total.
Paradoxically, the most basic form of @command{register} is almost
-never used, since it displays every transaction:
+never used, since it displays every posting:
@example
ledger reg
@@ -546,7 +1694,7 @@ reports:
50 AAPL
@end smallexample
-This rather verbose output shows every account transaction in
+This rather verbose output shows every account posting in
@file{sample.dat}, and how it affects the running total. The final
total is identical to what we saw with the plain @command{balance}
command. To see how things really balance, we can use @samp{--real
@@ -573,10 +1721,10 @@ Reports:
Here we see that everything balances to zero in the end, as it must.
-@subsubsection Specific register queries
+@subsection Specific register queries
The most common use of the register command is to summarize
-transactions based on the account(s) they affect. Using
+postings based on the account(s) they affect. Using
@file{sample.dat} as as example, we could look at all book purchases
using:
@@ -604,39 +1752,39 @@ Reports:
2004/05/29 Credit card company Liabilities:MasterCard $20.00 $20.00
@end smallexample
-There are many reporting options for tailoring which transactions are
+There are many reporting options for tailoring which postings are
found, and also how to summarize the various amounts and totals that
result. These are plumbed in greater depth below.
-@subsection Selecting transactions
+@section Selecting postings
Although the easiest way to use the register is to report all the
-transactions affecting a set of accounts, it can often result in more
+postings affecting a set of accounts, it can often result in more
information than you want. To cope with an ever-growing amount of
data, there are several options which can help you pinpoint your
-report to exactly the transactions that interest you most. This is
+report to epostly the postings that interest you most. This is
called the ``calculation'' phase of Ledger. All of its related
options are documented under @option{--help-calc}.
-@subsubsection By date
+@subsection By date
-@c -c, --current show only current and past entries (not future)
+@c -c, --current show only current and past transactions (not future)
-@option{--current}(@option{-c}) displays entries occurring on or
-before the current date. Any entry recorded for a future date will be
+@option{--current}(@option{-c}) displays transactions occurring on or
+before the current date. Any transaction recorded for a future date will be
ignored, as if it had not been seen. This is useful if you happen to
-pre-record entries, but still wish to view your balances in terms of
+pre-record transactions, but still wish to view your balances in terms of
what is available today.
@c -b, --begin DATE set report begin date
@c -e, --end DATE set report end date
@option{--begin DATE} (@option{-b DATE}) limits the report to only
-those entries occurring on or after @var{DATE}. The running total in
-the register will start at zero with the first transaction, even if
-there are earlier entries.
+those transactions occurring on or after @var{DATE}. The running total in
+the register will start at zero with the first posting, even if
+there are earlier transactions.
-To limit the display only, but still add earlier transactions to the
+To limit the display only, but still add earlier postings to the
running total, use the display expression @samp{-d 'd>=[DATE]'}):
@example
@@ -650,7 +1798,7 @@ Reports:
2004/05/27 Credit card company Assets:Bank:Checking $-20.00 $2,980.00
@end smallexample
-In this example, the displayed transactions start from @samp{5/14},
+In this example, the displayed postings start from @samp{5/14},
but the calculated total starts from the beginning of @samp{may}.
@option{--end DATE} (@option{-e DATE}) states when reporting should
@@ -670,7 +1818,7 @@ ledger -b "last month" bal
@end example
@c -p, --period STR report using the given period
-@c --period-sort EXPR sort each report period's entries by EXPR
+@c --period-sort EXPR sort each report period's transactions by EXPR
To constrain the report to a specific time period, use
@option{--period} (@option{-p}). A time period may have both a
@@ -703,61 +1851,61 @@ This command is identical to:
ledger -p "monthly in 2004" reg ^expenses
@end example
-The transactions within a period may be sorted using
+The postings within a period may be sorted using
@option{--period-sort}, which takes a value expression. This is
similar to the @option{--sort} option, except that it sorts within
-each period entry, rather than sorting all transactions in the report.
+each period transaction, rather than sorting all postings in the report.
See the documentation on @option{--sort} below for more details.
-@subsubsection By status
+@subsection By status
-By default, all regular transactions are included in each report. To
-limit the report to certain kinds of transactions, use one or more of
+By default, all regular postings are included in each report. To
+limit the report to certain kinds of postings, use one or more of
the following options:
@table @option
@item -C, --cleared
-Consider only cleared transactions.
+Consider only cleared postings.
@item -U, --uncleared
-Consider only uncleared and pending transactions.
+Consider only uncleared and pending postings.
@item -R, --real
-Consider only real (non-virtual) transactions.
+Consider only real (non-virtual) postings.
@item -L, --actual
-Consider only actual (non-automated) transactions.
+Consider only actual (non-automated) postings.
@end table
-Cleared transactions are indicated by an asterix placed just before
-the payee name in a transaction. The meaning of this flag is up to
-the user, but typically it means that an entry has been seen on a
-financial statement. Pending transactions use an exclamation mark in
+Cleared postings are indicated by an asterix placed just before
+the payee name in a posting. The meaning of this flag is up to
+the user, but typically it means that a transaction has been seen on a
+financial statement. Pending postings use an exclamation mark in
the same position, but are mainly used only by reconciling software.
-Uncleared transactions are for things like uncashed checks, credit
+Uncleared postings are for things like uncashed checks, credit
charges that haven't appeared on a statement yet, etc.
-Real transactions are all non-virtual transactions, where the account
+Real postings are all non-virtual postings, where the account
name is not surrounded by parentheses or square brackets. Virtual
-transactions are useful for showing a transfer of money that never
+postings are useful for showing a transfer of money that never
really happened, like money set aside for savings without actually
transferring it from the parent account.
-Actual transactions are those not generated, either as part of an
-automated entry, or a budget or forecast report. A useful of when you
-might like to filter out generated transactions is with a budget:
+Actual postings are those not generated, either as part of an
+automated transaction, or a budget or forecast report. A useful of when you
+might like to filter out generated postings is with a budget:
@example
ledger --budget --actual reg ^expenses
@end example
-This command outputs all transactions affecting a budgeted account,
+This command outputs all postings affecting a budgeted account,
but without subtracting the budget amount (because the generated
-transactions are suppressed with @option{--actual}). The report shows
+postings are suppressed with @option{--actual}). The report shows
how much you actually spent on budgeted items.
-@subsubsection By relationship
+@subsection By relationship
-@c -r, --related calculate report using related transactions
+@c -r, --related calculate report using related postings
-Normally, a register report includes only the transactions that match
+Normally, a register report includes only the postings that match
the regular expressions specified after the command word. For
example, to report all expenses:
@@ -771,8 +1919,8 @@ This reports:
2004/05/29 Book Store Expenses:Books $20.00 $20.00
@end smallexample
-Using @option{--related} (@option{-r}) reports the transactions that
-did not match your query, but only in entries that otherwise would
+Using @option{--related} (@option{-r}) reports the postings that
+did not match your query, but only in transactions that otherwise would
have matched. This has the effect of indicating where money came
from, or when to:
@@ -786,14 +1934,14 @@ Reports:
2004/05/29 Book Store Liabilities:MasterCard $20.00 $20.00
@end smallexample
-@subsubsection By budget
+@subsection By budget
-@c --budget generate budget entries based on FILE
+@c --budget generate budget transactions based on FILE
There is more information about budgeting and forecasting in
@ref{Budgeting and forecasting}. Basically, if you have any period
-entries in your ledger file, you can use these options. A period
-entry looks like:
+transactions in your ledger file, you can use these options. A period
+transaction looks like:
@example
~ Monthly
@@ -801,13 +1949,13 @@ entry looks like:
Income:Salary
@end example
-The difference from a regular entry is that the first line begins with
+The difference from a regular transaction is that the first line begins with
a tilde (~), and instead of a payee there's a period expression
-(@ref{Period expressions}). Otherwise, a period entry is in every
-other way the same as a regular entry.
+(@ref{Period expressions}). Otherwise, a period transaction is in every
+other way the same as a regular transaction.
-With such an entry in your ledger file, the @option{--budget} option
-will report only transactions that match a budgeted account. Using
+With such a transaction in your ledger file, the @option{--budget} option
+will report only postings that match a budgeted account. Using
@file{sample.dat} from above:
@example
@@ -817,36 +1965,36 @@ ledger --budget reg ^income
Reports:
@smallexample
-2004/05/01 Budget entry Income:Salary $500.00 $500.00
+2004/05/01 Budget transaction Income:Salary $500.00 $500.00
2004/05/14 Pay day Income:Salary $-500.00 0
@end smallexample
-The final total is zero, indicating that the budget matched exactly
+The final total is zero, indicating that the budget matched epostly
for the reported period. Budgeting is most often helpful with period
reporting; for example, to show monthly budget results use
@option{--budget -p monthly}.
-@c --add-budget show all transactions plus the budget
-@c --unbudgeted show only unbudgeted transactions
+@c --add-budget show all postings plus the budget
+@c --unbudgeted show only unbudgeted postings
-The @option{--add-budget} option reports all matching transactions in
-addition to budget transactions; while @option{--unbudgeted} shows
+The @option{--add-budget} option reports all matching postings in
+addition to budget postings; while @option{--unbudgeted} shows
only those that don't match a budgeted account. To summarize:
@table @option
@item --budget
-Show transactions matching budgeted accounts.
+Show postings matching budgeted accounts.
@item --unbudgeted
-Show transactions matching unbudgeted accounts.
+Show postings matching unbudgeted accounts.
@item --add-budget
-Show both budgeted and unbudgeted transactions together (i.e., add the
-generated budget transactions to the regular report).
+Show both budgeted and unbudgeted postings together (i.e., add the
+generated budget postings to the regular report).
@end table
-@c --forecast EXPR generate forecast entries while EXPR is true
+@c --forecast EXPR generate forecast transactions while EXPR is true
A report with the @option{--forecast} option will add budgeted
-transactions while the specified value expression is true. For
+postings while the specified value expression is true. For
example:
@example
@@ -857,14 +2005,14 @@ Reports:
@smallexample
2004/05/14 Pay day Income:Salary $-500.00 $-500.00
-2004/12/01 Forecast entry Income:Salary $-500.00 $-1,000.00
-2005/01/01 Forecast entry Income:Salary $-500.00 $-1,500.00
+2004/12/01 Forecast transaction Income:Salary $-500.00 $-1,000.00
+2005/01/01 Forecast transaction Income:Salary $-500.00 $-1,500.00
@end smallexample
The date this report was made was November 5, 2004; the reason the
-first forecast entry is in december is that forecast entries are only
+first forecast transaction is in december is that forecast transactions are only
added for the future, and they only stop after the value expression
-has matched at least once, which is why the January entry appears. A
+has matched at least once, which is why the January transaction appears. A
forecast report can be very useful for determining when money will run
out in an account, or for projecting future cash flow:
@@ -886,9 +2034,9 @@ of the above command (in November 2004) is:
2008/01/01 - 2008/01/01 Income:Salary $-500.00 $-19,480.00
@end smallexample
-@subsubsection By value expression
+@subsection By value expression
-@c -l, --limit EXPR calculate only transactions matching EXPR
+@c -l, --limit EXPR calculate only postings matching EXPR
Value expressions can be quite complex, and are treated more fully in
@ref{Value expressions}. They can be used for limiting a report with
@@ -902,8 +2050,8 @@ ledger -l '(/income/&d>=[aug])|(/expenses/&d>=[oct])' reg
The basic form of this value expression is @samp{(A&B)|(A&B)}. The
@samp{A} in each part matches against an account name with
@samp{/name/}, while each @samp{B} part compares the date of the
-transaction (@samp{d}) with a specified month. The resulting report
-will contain only transactions which match the value expression.
+posting (@samp{d}) with a specified month. The resulting report
+will contain only postings which match the value expression.
@c -t, --amount EXPR use EXPR to calculate the displayed amount
@c -T, --total EXPR use EXPR to calculate the displayed total
@@ -911,14 +2059,14 @@ will contain only transactions which match the value expression.
Another use of value expressions is to calculate the amount reported
for each line of a register report, or for computing the subtotal of
each account shown in a balance report. This example divides each
-transaction amount by two:
+posting amount by two:
@example
ledger -t 'a/2' reg ^exp
@end example
The @option{-t} option doesn't affect the running total, only how the
-transaction amount is displayed. To change the running total, use
+posting amount is displayed. To change the running total, use
@option{-T}. In that case, you will likely want to use the total
(@samp{O}) instead of the amount (@samp{a}):
@@ -926,21 +2074,21 @@ transaction amount is displayed. To change the running total, use
ledger -T 'O/2' reg ^exp
@end example
-@subsection Massaging register output
+@section Massaging register output
-Even after filtering down your data to just the transactions you're
-interested in, the default reporting method of one transaction per
+Even after filtering down your data to just the postings you're
+interested in, the default reporting method of one posting per
line is often still too much. To combat this complexity, it is
possible to ask Ledger to report the details to you in many different
forms, summarized in various ways. This is the ``display'' phase of
Ledger, and is documented under @option{--help-disp}.
-@subsubsection Summarizing
+@subsection Summarizing
-@c -n, --collapse register: collapse entries with multiple transactions
+@c -n, --collapse register: collapse transactions with multiple postings
-When multiple transactions relate to a single entry, they are reported
-as part of that entry. For example, in the case of @file{sample.dat}:
+When multiple postings relate to a single transaction, they are reported
+as part of that transaction. For example, in the case of @file{sample.dat}:
@example
ledger reg -- book
@@ -954,9 +2102,9 @@ Reports:
(Liabilities:Taxes) $-2.00 $-2.00
@end smallexample
-All three transactions are part of one entry, and as such the entry
-details are printed only once. To report every entry on a single
-line, use @option{-n} to collapse entries with multiple transactions:
+All three postings are part of one transaction, and as such the transaction
+details are printed only once. To report every transaction on a single
+line, use @option{-n} to collapse transactions with multiple postings:
@example
ledger -n reg -- book
@@ -997,18 +2145,18 @@ But if the @option{-s} option is added, the result becomes:
Assets:Brokerage $1,500.00 $2,980.00
@end smallexample
-When account subtotaling is used, only one entry is printed, and the
-date and name reflect the range of the combined transactions.
+When account subtotaling is used, only one transaction is printed, and the
+date and name reflect the range of the combined postings.
@c -P, --by-payee show summarized totals by payee
-With @option{-P}, transactions relating to the same payee are
-combined. In this case, the date of the combined entry is that of the
-latest transaction.
+With @option{-P}, postings relating to the same payee are
+combined. In this case, the date of the combined transaction is that of the
+latest posting.
@c -x, --comm-as-payee set commodity name as the payee, for reporting
-@option{-x} changes the payee name for each transaction to be the same
+@option{-x} changes the payee name for each posting to be the same
as the commodity it uses. This can be especially useful combined with
other options, like @option{-P}. For example:
@@ -1041,7 +2189,7 @@ matching accounts with a zero a balance, which are ordinarily
excluded. This can be useful to see all the accounts involved in a
report, even if some have no total.
-@subsubsection Quick periods
+@subsection Quick periods
Although the @option{-p} option (also @option{--period}) is much more
versatile, there are other options to make the most common period
@@ -1074,11 +2222,11 @@ Reports:
2004/05/14 Fridays Income:Salary $-500.00 $-480.00
@end smallexample
-@subsubsection Ordering and width
+@subsection Ordering and width
@c -S, --sort EXPR sort report according to the value expression EXPR
-The transactions displayed in a report are shown in the same order as
+The postings displayed in a report are shown in the same order as
they appear in the ledger file. To change the order and sort a
report, use the @option{--sort} option. @option{--sort} takes a value
expression to determine the value to sort against, making it possible
@@ -1101,7 +2249,7 @@ ledger --sort -T reg ^exp # reverse sort by amount total
ledger --sort UT reg ^exp # sort by abs amount total
@end example
-The @option{--sort} options sorts all transactions in a report. If
+The @option{--sort} options sorts all postings in a report. If
periods are used (such as @option{--monthly}), this can get somewhat
confusing. In that case, you'll probably want to sort within periods
using @option{--period-sort} instead of @option{--sort}.
@@ -1114,10 +2262,10 @@ acolumns, instead of 80. You are more likely then to see full payee
and account names, as well as properly formatted totals when
long-named commodities are used.
-If you want only the first or last N entries to be printed---which can
-be very useful for viewing the last 10 entries in your checking
+If you want only the first or last N transactions to be printed---which can
+be very useful for viewing the last 10 transactions in your checking
account, while also showing the cumulative balance from all
-entries---use the @option{--head} and/or @option{--tail} options. The
+transactions---use the @option{--head} and/or @option{--tail} options. The
two options may be used simultaneously, for example:
@example
@@ -1131,13 +2279,13 @@ data to a pager utility, such as @command{more} or @command{less}:
ledger --pager /usr/bin/less reg checking
@end example
-@subsubsection Averages and percentages
+@subsection Averages and percentages
-@c -A, --average report average transaction amount
+@c -A, --average report average posting amount
To see the running total changed to a running average, use
-@option{-A}. The final transaction's total will be the overall
-average of all displayed transactions. The works in conjunction with
+@option{-A}. The final posting's total will be the overall
+average of all displayed postings. The works in conjunction with
period reporting, so that you can see your monthly average expenses
with:
@@ -1176,11 +2324,11 @@ such as reviewing overall expenses:
ledger -%s -S T bal ^expenses
@end example
-@subsubsection Reporting total data
+@subsection Reporting total data
@c --totals in the "xml" report, include running total
-Normally in the @command{xml} report, only transaction amounts are
+Normally in the @command{xml} report, only posting amounts are
printed. To include the running total under a @samp{<total>} tag, use
@option{--totals}. This does not affect any other report.
@@ -1193,11 +2341,11 @@ commodities. This only makes sense if a single commodity appears in
the report, but can be quite useful for scripting, or passing the data
to Gnuplot. To show only the date and running total, use @option{-J}.
-@subsubsection Display by value expression
+@subsection Display by value expression
-@c -d, --display EXPR display only transactions matching EXPR
+@c -d, --display EXPR display only postings matching EXPR
-With @option{-d} you can decide which transactions (or accounts in the
+With @option{-d} you can decide which postings (or accounts in the
balance report) are displayed, according to a value expression. The
computed total is not affected, only the display. This can be very
useful for shortening a report without changing the running total:
@@ -1210,7 +2358,7 @@ This command shows the checking account's register, beginning from
last month, but with the running total reflecting the entire history
of the account.
-@subsubsection Change report format
+@subsection Change report format
@c -y, --date-format STR use STR as the date format (default: %Y/%m/%d)
@@ -1282,7 +2430,7 @@ options:
@end smallexample
@end table
-@subsection Standard queries
+@section Standard queries
If your ledger file uses the standard top-level accounts: Assets,
Liabilities, Income, Expenses, Equity: then the following queries will
@@ -1324,7 +2472,7 @@ ledger balance
Here I've set my Ledger environment variable to point to where my
ledger file is hiding. Thereafter, I needn't specify it again.
-@subsection Reporting balance totals
+@section Reporting balance totals
The balance command prints out the summarized balances of all my
top-level accounts, excluding sub-accounts. In order to see the
@@ -1358,1390 +2506,34 @@ food spending:
ledger balance expenses -food
@end example
-@subsection Reporting percentages
+@section Reporting percentages
-There is no built-in way to report transaction amounts or account
+There is no built-in way to report posting amounts or account
balances in terms of percentages
-@node Commands, Options, Usage overview, Running Ledger
-@section Commands
-
-@subsection balance
-
-The @command{balance} command reports the current balance of all
-accounts. It accepts a list of optional regexps, which confine the
-balance report to the matching accounts. If an account contains
-multiple types of commodities, each commodity's total is reported
-separately.
-
-@subsection register
-
-The @command{register} command displays all the transactions occurring
-in a single account, line by line. The account regexp must be
-specified as the only argument to this command. If any regexps occur
-after the required account name, the register will contain only those
-transactions that match. Very useful for hunting down a particular
-transaction.
-
-The output from @command{register} is very close to what a typical
-checkbook, or single-account ledger, would look like. It also shows a
-running balance. The final running balance of any register should
-always be the same as the current balance of that account.
-
-If you have Gnuplot installed, you may plot the amount or running
-total of any register by using the script @file{report}, which is
-included in the Ledger distribution. The only requirement is that you
-add either @option{-j} or @option{-J} to your register command, in
-order to plot either the amount or total column, respectively.
-
-@subsection print
-
-The @command{print} command prints out ledger entries in a textual
-format that can be parsed by Ledger. They will be properly formatted,
-and output in the most economic form possible. The ``print'' command
-also takes a list of optional regexps, which will cause only those
-transactions which match in some way to be printed.
-
-The @command{print} command can be a handy way to clean up a ledger
-file whose formatting has gotten out of hand.
-
-@subsection output
-
-The @command{output} command is very similar to the @command{print}
-command, except that it attempts to replicate the specified ledger
-file exactly. The format of the command is:
-
-@example
-ledger -f FILENAME output FILENAME
-@end example
-
-Where @file{FILENAME} is the name of the ledger file to output. The
-reason for specifying this command is that only entries contained
-within that file will be output, and not an included entries (as can
-happen with the @command{print} command).
-
-@subsection xml
-
-The @command{xml} command outputs results similar to what
-@command{print} and @command{register} display, but as an XML form.
-This data can then be read in and processed. Use the
-@option{--totals} option to include the running total with each
-transaction.
-
-@subsection emacs
-
-The @command{emacs} command outputs results in a form that can be read
-directly by Emacs Lisp. The format of the sexp is:
-
-@example
-((BEG-POS CLEARED DATE CODE PAYEE
- (ACCOUNT AMOUNT)...) ; list of transactions
- ...) ; list of entries
-@end example
-
-@subsection equity
-
-The @command{equity} command prints out accounts balances as if they
-were entries. This makes it easy to establish the starting balances
-for an account, such as when @ref{Archiving previous years}.
-
-@subsection prices
-
-The @command{prices} command displays the price history for matching
-commodities. The @option{-A} flag is useful with this report, to
-display the running average price, or @option{-D} to show each price's
-deviation from that average.
-
-There is also a @command{pricesdb} command which outputs the same
-information as @command{prices}, but does in a format that can be
-parsed by Ledger.
-
-@subsection entry
-
-The @command{entry} commands simplifies the creation of new entries.
-It works on the principle that 80% of all transactions are variants of
-earlier transactions. Here's how it works:
-
-Say you currently have this transaction in your ledger file:
-
-@smallexample
-2004/03/15 * Viva Italiano
- Expenses:Food $12.45
- Expenses:Tips $2.55
- Liabilities:MasterCard $-15.00
-@end smallexample
-
-Now it's @samp{2004/4/9}, and you've just eating at @samp{Viva
-Italiano} again. The exact amounts are different, but the overall
-form is the same. With the @command{entry} command you can type:
-
-@example
-ledger entry 2004/4/9 viva food 11 tips 2.50
-@end example
-
-This produces the following output:
-
-@smallexample
-2004/04/09 Viva Italiano
- Expenses:Food $11.00
- Expenses:Tips $2.50
- Liabilities:MasterCard $-13.50
-@end smallexample
-
-It works by finding a past transaction matching the regular expression
-@samp{viva}, and assuming that any accounts or amounts specified will
-be similar to that earlier transaction. If Ledger does not succeed in
-generating a new entry, an error is printed and the exit code is set
-to @samp{1}.
-
-There is a shell script in the distribution's @file{scripts} directory
-called @file{entry}, which simplifies the task of adding a new entry
-to your ledger. It launches @command{vi} to confirm that the entry
-looks appropriate.
-
-Here are a few more examples of the @command{entry} command, assuming
-the above journal entry:
-
-@example
-ledger entry 4/9 viva 11.50
-ledger entry 4/9 viva 11.50 checking # (from `checking')
-ledger entry 4/9 viva food 11.50 tips 8
-ledger entry 4/9 viva food 11.50 tips 8 cash
-ledger entry 4/9 viva food $11.50 tips $8 cash
-ledger entry 4/9 viva dining "DM 11.50"
-@end example
-
-@node Options, Format strings, Commands, Running Ledger
-@section Options
-
-With all of the reports, command-line options are useful to modify the
-output generated. These command-line options always occur before the
-command word. This is done to distinguish options from exclusive
-regular expressions, which also begin with a dash. The basic form for
-most commands is:
-
-@example
-ledger [OPTIONS] COMMAND [REGEXPS...] [-- [REGEXPS...]]
-@end example
-
-The @var{OPTIONS} and @var{REGEXPS} expressions are both optional.
-You could just use @samp{ledger balance}, without any options---which
-prints a summary of all accounts. But for more specific reporting, or
-to change the appearance of the output, options are needed.
-
-@menu
-* Basic options::
-* Report filtering::
-* Output customization::
-* Commodity reporting::
-* Environment variables::
-@end menu
-
-@node Basic options, Report filtering, Options, Options
-@subsection Basic options
-
-These are the most basic command options. Most likely, the user will
-want to set them using @ref{Environment variables}, instead of using
-actual command-line options:
-
-@option{--help} (@option{-h}) prints a summary of all the options, and
-what they are used for. This can be a handy way to remember which
-options do what. This help screen is also printed if ledger is run
-without a command.
-
-@option{--version} (@option{-v}) prints the current version of ledger
-and exits. This is useful for sending bug reports, to let the author
-know which version of ledger you are using.
-
-@option{--file FILE} (@option{-f FILE}) reads FILE as a ledger file.
-This command may be used multiple times. FILE may also be a list of
-file names separated by colons. Typically, the environment variable
-@env{LEDGER_FILE} is set, rather than using this command-line option.
-
-@option{--output FILE} (@option{-o FILE}) redirects output from any
-command to @var{FILE}. By default, all output goes to standard
-output.
-
-@option{--init-file FILE} (@option{-i FILE}) causes FILE to be read by
-ledger before any other ledger file. This file may not contain any
-transactions, but it may contain option settings. To specify options
-in the init file, use the same syntax as the command-line. Here's an
-example init file:
-
-@smallexample
---price-db ~/finance/.pricedb
-
-; ~/.ledgerrc ends here
-@end smallexample
-
-Option settings on the command-line or in the environment always take
-precedence over settings in the init file.
-
-@option{--cache FILE} identifies FILE as the default binary cache
-file. That is, if the ledger files to be read are specified using the
-environment variable @env{LEDGER_FILE}, then whenever a command is
-finished a binary copy will be written to the specified cache, to
-speed up the loading time of subsequent queries. This filename can
-also be given using the environment variable @env{LEDGER_CACHE}, or by
-putting the option into your init file. The @option{--no-cache}
-option causes Ledger to always ignore the binary cache.
-
-@option{--account NAME} (@option{-a NAME}) specifies the default
-account which QIF file transactions are assumed to relate to.
-
-@node Report filtering, Output customization, Basic options, Options
-@subsection Report filtering
-
-These options change which transactions affect the outcome of a
-report, in ways other than just using regular expressions:
-
-@option{--current}(@option{-c}) displays only entries occurring on or
-before the current date.
-
-@option{--begin DATE} (@option{-b DATE}) constrains the report to
-entries on or after @var{DATE}. Only entries after that date will be
-calculated, which means that the running total in the balance report
-will always start at zero with the first matching entry. (Note: This
-is different from using @option{--display} to constrain what is
-displayed).
-
-@option{--end DATE} (@option{-e DATE}) constrains the report so that
-entries on or after @var{DATE} are not considered. The ending date
-is inclusive.
-
-@option{--period STR} (@option{-p STR}) sets the reporting period
-to @var{STR}. This will subtotal all matching entries within each
-period separately, making it easy to see weekly, monthly, quarterly,
-etc., transaction totals. A period string can even specify the
-beginning and end of the report range, using simple terms like ``last
-june'' or ``next month''. For more using period expressions, see
-@ref{Period expressions}.
-
-@option{--period-sort EXPR} sorts the transactions within each
-reporting period using the value expression @var{EXPR}. This is most
-often useful when reporting monthly expenses, in order to view the
-highest expense categories at the top of each month:
-
-@example
-ledger -M --period-sort -At reg ^Expenses
-@end example
-
-@option{--cleared} (@option{-C}) displays only transactions whose entry
-has been marked ``cleared'' (by placing an asterix to the right of the
-date).
-
-@option{--uncleared} (@option{-U}) displays only transactions whose
-entry has not been marked ``cleared'' (i.e., if there is no asterix to
-the right of the date).
-
-@option{--real} (@option{-R}) displays only real transactions, not
-virtual. (A virtual transaction is indicated by surrounding the
-account name with parentheses or brackets; see the section on using
-virtual transactions for more information).
-
-@option{--actual} (@option{-L}) displays only actual transactions, and
-not those created due to automated transactions.
-
-@option{--related} (@option{-r}) displays transactions that are
-related to whichever transactions would otherwise have matched the
-filtering criteria. In the register report, this shows where money
-went to, or the account it came from. In the balance report, it shows
-all the accounts affected by entries having a related transaction.
-For example, if a file had this entry:
-
-@smallexample
-2004/03/20 Safeway
- Expenses:Food $65.00
- Expenses:Cash $20.00
- Assets:Checking $-85.00
-@end smallexample
-
-And the register command was:
-
-@example
-ledger -r register food
-@end example
-
-The following would be output, showing the transactions related to the
-transaction that matched:
-
-@smallexample
-2004/03/20 Safeway Expenses:Cash $-20.00 $-20.00
- Assets:Checking $85.00 $65.00
-@end smallexample
-
-@option{--budget} is useful for displaying how close your transactions
-meet your budget. @option{--add-budget} also shows unbudgeted
-transactions, while @option{--unbudgeted} shows only those.
-@option{--forecast} is a related option that projects your budget into
-the future, showing how it will affect future balances.
-@xref{Budgeting and forecasting}.
-
-@option{--limit EXPR} (@option{-l EXPR}) limits which transactions
-take part in the calculations of a report.
-
-@option{--amount EXPR} (@option{-t EXPR}) changes the value expression
-used to calculate the ``value'' column in the @command{register}
-report, the amount used to calculate account totals in the
-@command{balance} report, and the values printed in the
-@command{equity} report. @xref{Value expressions}.
-
-@option{--total EXPR} (@option{-T EXPR}) sets the value expression
-used for the ``totals'' column in the @command{register} and
-@command{balance} reports.
-
-@node Output customization, Commodity reporting, Report filtering, Options
-@subsection Output customization
-
-These options affect only the output, but not which transactions are
-used to create it:
-
-@option{--collapse} (@option{-n}) causes entries in a
-@command{register} report with multiple transactions to be collapsed
-into a single, subtotaled entry.
-
-@option{--subtotal} (@option{-s}) causes all entries in a
-@command{register} report to be collapsed into a single, subtotaled
-entry.
-
-@option{--by-payee} (@option{-P}) reports subtotals by payee.
-
-@option{--comm-as-payee} (@option{-x}) changes the payee of every
-transaction to be the commodity used in that transaction. This can be
-useful when combined with other options, such as @option{-s}.
-
-@option{--empty} (@option{-E}) includes even empty accounts in the
-@command{balance} report.
-
-@option{--weekly} (@option{-W}) reports transaction totals by the
-week. The week begins on whichever day of the week begins the month
-containing that transaction. To set a specific begin date, use a
-period string, such as @samp{weekly from DATE}. @option{--monthly}
-(@option{-M}) reports transaction totals by month; @option{--yearly}
-(@option{-Y}) reports transaction totals by year. For more complex
-period, using the @option{--period} option described above.
-
-@option{--dow} reports transactions totals for each day of the week.
-This is an easy way to see if weekend spending is more than on
-weekdays.
-
-@option{--sort EXPR} (@option{-S EXPR}) sorts a report by comparing
-the values determined using the value expression @var{EXPR}. For
-example, using @option{-S -UT} in the balance report will sort account
-balances from greatest to least, using the absolute value of the
-total. For more on how to use value expressions, see @ref{Value
-expressions}.
-
-@option{--wide} (@option{-w}) causes the default @command{register}
-report to assume 132 columns instead of 80.
-
-@option{--head} causes only the first N entries to be printed. This
-is different from using the command-line utility @command{head}, which
-would limit to the first N transactions. @option{--tail} outputs only
-the last N entries. Both options may be used simultaneously. If a
-negative amount is given, it will invert the meaning of the flag
-(instead of the first five entries being printed, for example, it
-would print all but the first five).
-
-@option{--pager} tells Ledger to pass its output to the given pager
-program---very useful when the output is especially long. This
-behavior can be made the default by setting the @env{LEDGER_PAGER}
-environment variable.
-
-@option{--average} (@option{-A}) reports the average transaction
-value.
-
-@option{--deviation} (@option{-D}) reports each transaction's
-deviation from the average. It is only meaningful in the
-@command{register} and @command{prices} reports.
-
-@option{--percentage} (@option{-%}) shows account subtotals in the
-@command{balance} report as percentages of the parent account.
-
-@option{--totals} include running total information in the
-@command{xml} report.
-
-@option{--amount-data} (@option{-j}) changes the @command{register}
-report so that it output nothing but the date and the value column,
-and the latter without commodities. This is only meaningful if the
-report uses a single commodity. This data can then be fed to other
-programs, which could plot the date, analyze it, etc.
-
-@option{--total-data} (@option{-J}) changes the @command{register}
-report so that it output nothing but the date and totals column,
-without commodities.
-
-@option{--display EXPR} (@option{-d EXPR}) limits which transactions
-or accounts or actually displayed in a report. They might still be
-calculated, and be part of the running total of a register report, for
-example, but they will not be displayed. This is useful for seeing
-last month's checking transactions, against a running balance which
-includes all transaction values:
-
-@example
-ledger -d "d>=[last month]" reg checking
-@end example
-
-The output from this command is very different from the following,
-whose running total includes only transactions from the last month
-onward:
-
-@example
-ledger -p "last month" reg checking
-@end example
-
-Which is more useful depends on what you're looking to know: the total
-amount for the reporting range (@option{-p}), or simply a display
-restricted to the reporting range (using @option{-d}).
-
-@option{--date-format STR} (@option{-y STR}) changes the basic date
-format used by reports. The default uses a date like 2004/08/01,
-which represents the default date format of @samp{%Y/%m/%d}. To
-change the way dates are printed in general, the easiest way is to put
-@option{--date-format FORMAT} in the Ledger initialization file
-@file{~/.ledgerrc} (or the file referred to by @env{LEDGER_INIT}).
-
-@option{--format STR} (@option{-F STR}) sets the reporting format for
-whatever report ledger is about to make. @xref{Format strings}.
-There are also specific format commands for each report type:
-
-@itemize
-@item @option{--balance-format STR}
-@item @option{--register-format STR}
-@item @option{--print-format STR}
-@item @option{--plot-amount-format STR} (-j @command{register})
-@item @option{--plot-total-format STR} (-J @command{register})
-@item @option{--equity-format STR}
-@item @option{--prices-format STR}
-@item @option{--wide-register-format STR} (-w @command{register})
-@end itemize
-
-@node Commodity reporting, Environment variables, Output customization, Options
-@subsection Commodity reporting
-
-These options affect how commodity values are displayed:
-
-@option{--price-db FILE} sets the file that is used for recording
-downloaded commodity prices. It is always read on startup, to
-determine historical prices. Other settings can be placed in this
-file manually, to prevent downloading quotes for a specific, for
-example. This is done by adding a line like the following:
-
-@example
-; Don't download quotes for the dollar, or timelog values
-N $
-N h
-@end example
-
-@option{--price-exp MINS} (@option{-L MINS}) sets the expected
-freshness of price quotes, in minutes. That is, if the last known
-quote for any commodity is older than this value---and if
-@option{--download} is being used---then the Internet will be
-consulted again for a newer price. Otherwise, the old price is still
-considered to be fresh enough.
-
-@option{--download} (@option{-Q}) causes quotes to be automagically
-downloaded, as needed, by running a script named @command{getquote}
-and expecting that script to return a value understood by ledger. A
-sample implementation of a @command{getquote} script, implemented in
-Perl, is provided in the distribution. Downloaded quote price are
-then appended to the price database, usually specified using the
-environment variable @env{LEDGER_PRICE_DB}.
-
-There are several different ways that ledger can report the totals it
-displays. The most flexible way to adjust them is by using value
-expressions, and the @option{-t} and @option{-T} options. However,
-there are also several ``default'' reports, which will satisfy most
-users basic reporting needs:
-
-@table @code
-@item -O, --quantity
-Reports commodity totals (this is the default)
-
-@item -B, --basis
-Reports the cost basis for all transactions.
-
-@item -V, --market
-Reports the last known market value for all commodities.
-
-@item -g, --performance
-Reports the net gain/loss for each transaction in a @command{register}
-report.
-
-@item -G --gain
-Reports the net gain/loss for all commodities in the report that have
-a price history.
-@end table
-
-@node Environment variables, , Commodity reporting, Options
-@subsection Environment variables
-
-Every option to ledger may be set using an environment variable. If
-an option has a long name such @option{--this-option}, setting the
-environment variable @env{LEDGER_THIS_OPTION} will have the same
-affect as specifying that option on the command-line. Options on the
-command-line always take precedence over environment variable
-settings, however.
-
-Note that you may also permanently specify option values by placing
-option settings in the file @file{~/.ledgerrc}, for example:
-
-@example
---cache /tmp/.mycache
-@end example
-
-@node Format strings, Value expressions, Options, Running Ledger
-@section Format strings
-
-Format strings may be used to change the output format of reports.
-They are specified by passing a formatting string to the
-@option{--format} (@option{-F}) option. Within that string,
-constructs are allowed which make it possible to display the various
-parts of an account or transaction in custom ways.
-
-Within a format strings, a substitution is specified using a percent
-character (@samp{%}). The basic format of all substitutions is:
-
-@example
-%[-][MIN WIDTH][.MAX WIDTH]EXPR
-@end example
-
-If the optional minus sign (@samp{-}) follows the percent character,
-whatever is substituted will be left justified. The default is right
-justified. If a minimum width is given next, the substituted text
-will be at least that wide, perhaps wider. If a period and a maximum
-width is given, the substituted text will never be wider than this,
-and will be truncated to fit. Here are some examples:
-
-@example
-%-P An entry's payee, left justified
-%20P The same, right justified, at least 20 chars wide
-%.20P The same, no more than 20 chars wide
-%-.20P Left justified, maximum twenty chars wide
-@end example
-
-The expression following the format constraints can be a single
-letter, or an expression enclosed in parentheses or brackets. The
-allowable expressions are:
-
-@table @code
-@item %
-Inserts a percent sign.
-
-@item t
-Inserts the results of the value expression specified by @option{-t}.
-If @option{-t} was not specified, the current report style's value
-expression is used.
-
-@item T
-Inserts the results of the value expression specified by @option{-T}.
-If @option{-T} was not specified, the current report style's value
-expression is used.
-
-@item |
-Inserts a single space. This is useful if a width is specified, for
-inserting a certain number of spaces.
-
-@item _
-Inserts a space for each level of an account's depth. That is, if an
-account has two parents, this construct will insert two spaces. If a
-minimum width is specified, that much space is inserted for each level
-of depth. Thus @samp{%5_}, for an account with four parents, will
-insert twenty spaces.
-
-@item (EXPR)
-Inserts the amount resulting from the value expression given in
-parentheses. To insert five times the total value of an account, for
-example, one could say @samp{%12(5*O)}. Note: It's important to put
-the five first in that expression, so that the commodity doesn't get
-stripped from the total.
-
-@item [DATEFMT]
-Inserts the result of formatting a transaction's date with a date
-format string, exactly like those supported by @code{strftime}. For
-example: @samp{%[%Y/%m/%d %H:%M:%S]}.
-
-@item S
-Insert the pathname of the file from which the entry's data was read.
-
-@item B
-Inserts the beginning character position of that entry within the file.
-
-@item b
-Inserts the beginning line of that entry within the file.
-
-@item E
-Inserts the ending character position of that entry within the file.
-
-@item e
-Inserts the ending line of that entry within the file.
-
-@item D
-By default, this is the same as @samp{%[%Y/%m%/d]}. The date format
-used can be changed at any time with the @option{-y} flag, however.
-Using @samp{%D} gives the user more control over the way dates are
-output.
-
-@item d
-This is the same as the @samp{%D} option, unless the entry has an
-effective date, in which case it prints
-@samp{[ACTUAL_DATE=EFFECtIVE_DATE]}.
-
-@item X
-If a transaction has been cleared, this inserts @samp{*} followed by a
-space; otherwise nothing is inserted.
-
-@item Y
-This is the same as @samp{%X}, except that it only displays a state
-character if all of the member transactions have the same state.
-
-@item C
-Inserts the checking number for an entry, in parentheses, followed by
-a space; if none was specified, nothing is inserted.
-
-@item P
-Inserts the payee related to a transaction.
-
-@item a
-Inserts the optimal short name for an account. This is normally used
-in balance reports. It prints a parent account's name if that name
-has not been printed yet, otherwise it just prints the account's name.
-
-@item A
-Inserts the full name of an account.
-
-@item W
-This is the same as @samp{%A}, except that it first displays the
-transaction's state @emph{if the entry's transaction states are not
-all the same}, followed by the full account name. This is offered as
-a printing optimization, so that combined with @samp{%Y}, only the
-minimum amount of state detail is printed.
-
-@item o
-Inserts the ``optimized'' form of a transaction's amount. This is
-used by the print report. In some cases, this inserts nothing; in
-others, it inserts the transaction amount and its cost. It's use is
-not recommend unless you are modifying the print report.
-
-@item n
-Inserts the note associated with a transaction, preceded by two spaces
-and a semi-colon, if it exists. Thus, no none becomes an empty
-string, while the note @samp{foo} is substituted as @samp{ ; foo}.
-
-@item N
-Inserts the note associated with a transaction, if one exists.
-
-@item /
-The @samp{%/} construct is special. It separates a format string
-between what is printed for the first transaction of an entry, and
-what is printed for all subsequent transactions. If not used, the
-same format string is used for all transactions.
-@end table
-
-@node Value expressions, Period expressions, Format strings, Running Ledger
-@section Value expressions
-
-Value expressions are an expression language used by Ledger to
-calculate values used by the program for many different purposes:
-
-@enumerate
-@item
-The values displayed in reports
-@item
-For predicates (where truth is anything non-zero), to determine which
-transactions are calculated (@option{-l}) or displayed (@option{-d}).
-@item
-For sorting criteria, to yield the sort key.
-@item
-In the matching criteria used by automated transactions.
-@end enumerate
-
-Value expressions support most simple math and logic operators, in
-addition to a set of one letter functions and variables. A function's
-argument is whatever follows it. The following is a display predicate
-that I use with the @command{balance} command:
-
-@example
-ledger -d /^Liabilities/?T<0:UT>100 balance
-@end example
-
-The effect is that account totals are displayed only if: 1) A
-Liabilities account has a total less than zero; or 2) the absolute
-value of the account's total exceeds 100 units of whatever commodity
-contains. If it contains multiple commodities, only one of them must
-exceed 100 units.
-
-Display predicates are also very handy with register reports, to
-constrain which entries are printed. For example, the following
-command shows only entries from the beginning of the current month,
-while still calculating the running balance based on all entries:
-
-@example
-ledger -d "d>[this month]" register checking
-@end example
-
-This advantage to this command's complexity is that it prints the
-running total in terms of all entries in the register. The following,
-simpler command is similar, but totals only the displayed
-transactions:
-
-@example
-ledger -b "this month" register checking
-@end example
-
-@subsection Variables
-
-Below are the one letter variables available in any value expression.
-For the register and print commands, these variables relate to
-individual transactions, and sometimes the account affected by a
-transaction. For the balance command, these variables relate to
-accounts---often with a subtle difference in meaning. The use of each
-variable for both is specified.
-
-@table @code
-@item t
-This maps to whatever the user specified with @option{-t}. In a
-register report, @option{-t} changes the value column; in a balance
-report, it has no meaning by default. If @option{-t} was not
-specified, the current report style's value expression is used.
-
-@item T
-This maps to whatever the user specified with @option{-T}. In a
-register report, @option{-T} changes the totals column; in a balance
-report, this is the value given for each account. If @option{-T} was
-not specified, the current report style's value expression is used.
-
-@item m
-This is always the present moment/date.
-@end table
-
-@subsubsection Transaction/account details
-
-@table @code
-@item d
-A transaction's date, as the number of seconds past the epoch. This
-is always ``today'' for an account.
-
-@item a
-The transaction's amount; the balance of an account, without
-considering children.
-
-@item b
-The cost of a transaction; the cost of an account, without its
-children.
-
-@item v
-The market value of a transaction, or an account without its children.
-
-@item g
-The net gain (market value minus cost basis), for a transaction or an
-account without its children. It is the same as @samp{v-b}.
-
-@item l
-The depth (``level'') of an account. If an account has one parent,
-it's depth is one.
-
-@item n
-The index of a transaction, or the count of transactions affecting an
-account.
-
-@item X
-1 if a transaction's entry has been cleared, 0 otherwise.
-
-@item R
-1 if a transaction is not virtual, 0 otherwise.
-
-@item Z
-1 if a transaction is not automated, 0 otherwise.
-@end table
-
-@subsubsection Calculated totals
-
-@table @code
-@item O
-The total of all transactions seen so far, or the total of an account
-and all its children.
-
-@item N
-The total count of transactions affecting an account and all its
-children.
-
-@item B
-The total cost of all transactions seen so far; the total cost of an
-account and all its children.
-
-@item V
-The market value of all transactions seen so far, or of an account and
-all its children.
-
-@item G
-The total net gain (market value minus cost basis), for a series of
-transactions, or an account and its children. It is the same as
-@samp{V-B}.
-@end table
-
-@subsection Functions
-
-The available one letter functions are:
-
-@table @code
-@item -
-Negates the argument.
-
-@item U
-The absolute (unsigned) value of the argument.
-
-@item S
-Strips the commodity from the argument.
-
-@item A
-The arithmetic mean of the argument; @samp{Ax} is the same as
-@samp{x/n}.
-
-@item P
-The present market value of the argument. The syntax @samp{P(x,d)} is
-supported, which yields the market value at time @samp{d}. If no date
-is given, then the current moment is used.
-@end table
-
-@subsection Operators
-
-The binary and ternary operators, in order of precedence, are:
-
-@enumerate
-@item @samp{* /}
-@item @samp{+ -}
-@item @samp{! < > =}
-@item @samp{& | ?:}
-@end enumerate
-
-@subsection Complex expressions
-
-More complicated expressions are possible using:
-
-@table @code
-@item NUM
-A plain integer represents a commodity-less amount.
-
-@item @{AMOUNT@}
-An amount in braces can be any kind of amount supported by ledger,
-with or without a commodity. Use this for decimal values.
-
-@item /REGEXP/
-@item W/REGEXP/
-A regular expression that matches against an account's full name. If
-a transaction, this will match against the account affected by the
-transaction.
-
-@item //REGEXP/
-@item p/REGEXP/
-A regular expression that matches against an entry's payee name.
-
-@item ///REGEXP/
-@item w/REGEXP/
-A regular expression that matches against an account's base name. If
-a transaction, this will match against the account affected by the
-transaction.
-
-@item c/REGEXP/
-A regular expression that matches against the entry code (the text
-that occurs between parentheses before the payee name).
-
-@item e/REGEXP/
-A regular expression that matches against a transaction's note, or
-comment field.
-
-@item (EXPR)
-A sub-expression is nested in parenthesis. This can be useful passing
-more complicated arguments to functions, or for overriding the natural
-precedence order of operators.
-
-@item [DATE]
-Useful specifying a date in plain terms. For example, you could say
-@samp{[2004/06/01]}.
-@end table
-
-@node Period expressions, File format, Value expressions, Running Ledger
-@section Period expressions
-
-A period expression indicates a span of time, or a reporting interval,
-or both. The full syntax is:
-
-@example
-[INTERVAL] [BEGIN] [END]
-@end example
-
-The optional @var{INTERVAL} part may be any one of:
-
-@example
-every day
-every week
-every monthly
-every quarter
-every year
-every N days # N is any integer
-every N weeks
-every N months
-every N quarters
-every N years
-daily
-weekly
-biweekly
-monthly
-bimonthly
-quarterly
-yearly
-@end example
-
-After the interval, a begin time, end time, both or neither may be
-specified. As for the begin time, it can be either of:
-
-@example
-from <SPEC>
-since <SPEC>
-@end example
-
-The end time can be either of:
-
-@example
-to <SPEC>
-until <SPEC>
-@end example
-
-Where @var{SPEC} can be any of:
-
-@example
-2004
-2004/10
-2004/10/1
-10/1
-october
-oct
-this week # or day, month, quarter, year
-next week
-last week
-@end example
-
-The beginning and ending can be given at the same time, if it spans a
-single period. In that case, just use @var{SPEC} by itself. In that
-case, the period @samp{oct}, for example, will cover all the days in
-october. The possible forms are:
-
-@example
-<SPEC>
-in <SPEC>
-@end example
-
-Here are a few examples of period expressions:
-
-@example
-monthly
-monthly in 2004
-weekly from oct
-weekly from last month
-from sep to oct
-from 10/1 to 10/5
-monthly until 2005
-from apr
-until nov
-last oct
-weekly last august
-@end example
-
-@node File format, Some typical queries, Period expressions, Running Ledger
-@section File format
-
-The ledger file format is quite simple, but also very flexible. It
-supports many options, though typically the user can ignore most of
-them. They are summarized below.
-
-The initial character of each line determines what the line means, and
-how it should be interpreted. Allowable initial characters are:
-
-@table @code
-@item NUMBER
-A line beginning with a number denotes an entry. It may be followed
-by any number of lines, each beginning with whitespace, to denote the
-entry's account transactions. The format of the first line is:
-
-@example
-DATE[=EDATE] [*|!] [(CODE)] DESC
-@end example
-
-If @samp{*} appears after the date (with optional effective date), it
-indicates the entry is ``cleared'', which can mean whatever the user
-wants it t omean. If @samp{!} appears after the date, it indicates d
-the entry is ``pending''; i.e., tentatively cleared from the user's
-point of view, but not yet actually cleared. If a @samp{CODE} appears
-in parentheses, it may be used to indicate a check number, or the type
-of the transaction. Following these is the payee, or a description of
-the transaction.
-
-The format of each following transaction is:
-
-@example
- ACCOUNT AMOUNT [; NOTE]
-@end example
-
-The @samp{ACCOUNT} may be surrounded by parentheses if it is a virtual
-transactions, or square brackets if it is a virtual transactions that
-must balance. The @samp{AMOUNT} can be followed by a per-unit
-transaction cost, by specifying @samp{@@ AMOUNT}, or a complete
-transaction cost with @samp{@@@@ AMOUNT}. Lastly, the @samp{NOTE} may
-specify an actual and/or effective date for the transaction by using
-the syntax @samp{[ACTUAL_DATE]} or @samp{[=EFFECTIVE_DATE]} or
-@samp{[ACTUAL_DATE=EFFECtIVE_DATE]}.
-
-@item =
-An automated entry. A value expression must appear after the equal
-sign.
-
-After this initial line there should be a set of one or more
-transactions, just as if it were normal entry. If the amounts of the
-transactions have no commodity, they will be applied as modifiers to
-whichever real transaction is matched by the value expression.
-
-@item ~
-A period entry. A period expression must appear after the tilde.
-
-After this initial line there should be a set of one or more
-transactions, just as if it were normal entry.
-
-@item !
-A line beginning with an exclamation mark denotes a command directive.
-It must be immediately followed by the command word. The supported
-commands are:
-
-@table @samp
-@item !include
-Include the stated ledger file.
-
-@item !account
-The account name is given is taken to be the parent of all
-transactions that follow, until @samp{!end} is seen.
-
-@item !end
-Ends an account block.
-@end table
-
-@item ;
-A line beginning with a colon indicates a comment, and is ignored.
-
-@item Y
-If a line begins with a capital Y, it denotes the year used for all
-subsequent entries that give a date without a year. The year should
-appear immediately after the Y, for example: @samp{Y2004}. This is
-useful at the beginning of a file, to specify the year for that file.
-If all entries specify a year, however, this command has no effect.
-
-@item P
-Specifies a historical price for a commodity. These are usually found
-in a pricing history file (see the @option{-Q} option). The syntax
-is:
-@example
-P DATE SYMBOL PRICE
-@end example
-
-@item N SYMBOL
-Indicates that pricing information is to be ignored for a given
-symbol, nor will quotes ever be downloaded for that symbol. Useful
-with a home currency, such as the dollar ($). It is recommended that
-these pricing options be set in the price database file, which
-defaults to @file{~/.pricedb}. The syntax for this command is:
-@example
-N SYMBOL
-@end example
-
-@item D AMOUNT
-Specifies the default commodity to use, by specifying an amount in the
-expected format. The @command{entry} command will use this commodity
-as the default when none other can be determined. This command may be
-used multiple times, to set the default flags for different
-commodities; whichever is seen last is used as the default commodity.
-For example, to set US dollars as the default commodity, while also
-setting the thousands flag and decimal flag for that commodity, use:
-@example
-D $1,000.00
-@end example
-
-@item C AMOUNT1 = AMOUNT2
-Specifies a commodity conversion, where the first amount is given to
-be equivalent to the second amount. The first amount should use the
-decimal precision desired during reporting:
-@example
-C 1.00 Kb = 1024 bytes
-@end example
-
-@item i, o, b, h
-These four relate to timeclock support, which permits ledger to read
-timelog files. See the timeclock's documentation for more info on the
-syntax of its timelog files.
-@end table
-
-@node Some typical queries, Budgeting and forecasting, File format, Running Ledger
-@section Some typical queries
-
-A query such as the following shows all expenses since last
-October, sorted by total:
-
-@example
-ledger -b "last oct" -s -S T bal ^expenses
-@end example
-
-From left to right the options mean: Show entries since October, 2003;
-show all sub-accounts; sort by the absolute value of the total; and
-report the balance for all expenses.
-
-@subsection Reporting monthly expenses
-
-The following query makes it easy to see monthly expenses, with each
-month's expenses sorted by the amount:
-
-@example
-ledger -M --period-sort t reg ^expenses
-@end example
-
-Now, you might wonder where the money came from to pay for these
-things. To see that report, add @option{-r}, which shows the
-``related account'' transactions:
-
-@example
-ledger -M --period-sort t -r reg ^expenses
-@end example
-
-But maybe this prints too much information. You might just want to
-see how much you're spending with your MasterCard. That kind of query
-requires the use of a display predicate, since the transactions
-calculated must match @samp{^expenses}, while the transactions
-displayed must match @samp{mastercard}. The command would be:
-
-@example
-ledger -M -r -d /mastercard/ reg ^expenses
-@end example
-
-This query says: Report monthly subtotals; report the ``related
-account'' transactions; display only related transactions whose
-account matches @samp{mastercard}, and base the calculation on
-transactions matching @samp{^expenses}.
-
-This works just as well for report the overall total, too:
-
-@example
-ledger -s -r -d /mastercard/ reg ^expenses
-@end example
-
-The @option{-s} option subtotals all transactions, just as @option{-M}
-subtotaled by the month. The running total in both cases is off,
-however, since a display expression is being used.
-
-@subsection Visualizing with Gnuplot
-
-If you have @command{Gnuplot} installed, you can graph any of the
-above register reports. The script to do this is included in the
-ledger distribution, and is named @file{scripts/report}. Install
-@file{report} anywhere along your @env{PATH}, and then use
-@command{report} instead of @command{ledger} when doing a register
-report. The only thing to keep in mind is that you must specify
-@option{-j} or @option{-J} to indicate whether Gnuplot should plot the
-amount, or the running total. For example, this command plots total
-monthly expenses made on your MasterCard.
-
-@example
-report -j -M -r -d /mastercard/ reg ^expenses
-@end example
-
-The @command{report} script is a very simple Bourne shell script, that
-passes a set of scripted commands to Gnuplot. Feel free to modify the
-script to your liking, since you may prefer histograms to line plots,
-for example.
-
-@subsubsection Typical plots
-
-Here are some useful plots:
-
-@smallexample
-report -j -M reg ^expenses # monthly expenses
-report -J reg checking # checking account balance
-report -J reg ^income ^expenses # cash flow report
-
-# net worth report, ignoring non-$ transactions
-
-report -J -l "Ua>=@{\$0.01@}" reg ^assets ^liab
-
-# net worth report starting last February. the use of a display
-# predicate (-d) is needed, otherwise the balance will start at
-# zero, and thus the y-axis will not reflect the true balance
-
-report -J -l "Ua>=@{\$0.01@}" -d "d>=[last feb]" reg ^assets ^liab
-@end smallexample
-
-The last report uses both a calculation predicate (@option{-l}) and a
-display predicate (@option{-d}). The calculation predicates limits
-the report to transactions whose amount is greater than $1 (which can
-only happen if the transaction amount is in dollars). The display
-predicate limits the entries @emph{displayed} to just those since last
-February, even those entries from before then will be computed as part
-of the balance.
-
-@node Budgeting and forecasting, , Some typical queries, Running Ledger
-@section Budgeting and forecasting
-
-@subsection Budgeting
-
-Keeping a budget allows you to pay closer attention to your income and
-expenses, by reporting how far your actual financial activity is from
-your expectations.
-
-To start keeping a budget, put some period entries at the top of your
-ledger file. A period entry is almost identical to a regular entry,
-except that it begins with a tilde and has a period expression in
-place of a payee. For example:
-
-@smallexample
-~ Monthly
- Expenses:Rent $500.00
- Expenses:Food $450.00
- Expenses:Auto:Gas $120.00
- Expenses:Insurance $150.00
- Expenses:Phone $125.00
- Expenses:Utilities $100.00
- Expenses:Movies $50.00
- Expenses $200.00 ; all other expenses
- Assets
-
-~ Yearly
- Expenses:Auto:Repair $500.00
- Assets
-@end smallexample
-
-These two period entries give the usual monthly expenses, as well as
-one typical yearly expense. For help on finding out what your average
-monthly expense is for any category, use a command like:
-
-@example
-ledger -p "this year" -MAs bal ^expenses
-@end example
-
-The reported totals are the current year's average for each account.
-
-Once these period entries are defined, creating a budget report is as
-easy as adding @option{--budget} to the command-line. For example, a
-typical monthly expense report would be:
-
-@example
-ledger -M reg ^exp
-@end example
-
-To see the same report balanced against your budget, use:
-
-@example
-ledger --budget -M reg ^exp
-@end example
-
-A budget report includes only those accounts that appear in the
-budget. To see all expenses balanced against the budget, use
-@option{--add-budget}. You can even see only the unbudgeted expenses
-using @option{--unbudgeted}:
-
-@example
-ledger --unbudgeted -M reg ^exp
-@end example
-
-You can also use these flags with the @command{balance} command.
-
-@subsection Forecasting
-
-Sometimes it's useful to know what your finances will look like in the
-future, such as determining when an account will reach zero. Ledger
-makes this easy to do, using the same period entries as are used for
-budgeting. An example forecast report can be generated with:
-
-@example
-ledger --forecast "T>@{\$-500.00@}" register ^assets ^liabilities
-@end example
-
-This report continues outputting transactions until the running total
-is greater than $-500.00. A final transaction is always output, to
-show you what the total afterwards would be.
-
-Forecasting can also be used with the balance report, but by date
-only, and not against the running total:
-
-@example
-ledger --forecast "d<[2010]" bal ^assets ^liabilities
-@end example
-
-@node Keeping a ledger, Using XML, Running Ledger, Top
-@chapter Keeping a ledger
-
-The most important part of accounting is keeping a good ledger. If
-you have a good ledger, tools can be written to work whatever
-mathematically tricks you need to better understand your spending
-patterns. Without a good ledger, no tool, however smart, can help
-you.
-
-The Ledger program aims at making ledger entry as simple as possible.
-Since it is a command-line tool, it does not provide a user interface
-for keeping a ledger. If you like, you may use GnuCash to maintain
-your ledger, in which case the Ledger program will read GnuCash's data
-files directly. In that case, read the GnuCash manual now, and skip
-to the next chapter.
-
-If you are not using GnuCash, but a text editor to maintain your
-ledger, read on. Ledger has been designed to make data entry as
-simple as possible, by keeping the ledger format easy, and also by
-automagically determining as much information as possible based on the
-nature of your entries.
-
-For example, you do not need to tell Ledger about the accounts you
-use. Any time Ledger sees a transaction involving an account it knows
-nothing about, it will create it. If you use a commodity that is new
-to Ledger, it will create that commodity, and determine its display
-characteristics (placement of the symbol before or after the amount,
-display precision, etc) based on how you used the commodity in the
-transaction.
-
-Here is the Pacific Bell example from above, given as a Ledger
-transaction:
-
-@smallexample
-9/29 (100) Pacific Bell
- Expenses:Utilities:Phone $23.00
- Assets:Checking $-23.00
-@end smallexample
-
-As you can see, it is very similar to what would be written on paper,
-minus the computed balance totals, and adding in account names that
-work better with Ledger's scheme of things. In fact, since Ledger is
-smart about many things, you don't need to specify the balanced
-amount, if it is the same as the first line:
-
-@smallexample
-9/29 (100) Pacific Bell
- Expenses:Utilities:Phone $23.00
- Assets:Checking
-@end smallexample
-
-For this entry, Ledger will figure out that $-23.00 must come from
-@samp{Assets:Checking} in order to balance the entry.
+@node Ledger in Practice, , Ledger Tutorial, Top
+@chapter Ledger in Practice
@menu
* Stating where money goes::
* Assets and Liabilities::
+* Typical queries::
+* Budgeting and forecasting::
* Commodities and Currencies::
* Accounts and Inventories::
* Understanding Equity::
* Dealing with Petty Cash::
* Working with multiple funds and accounts::
* Archiving previous years::
-* Virtual transactions::
-* Automated transactions::
+* Virtual postings::
+* Automated postings::
* Using Emacs to Keep Your Ledger::
* Using GnuCash to Keep Your Ledger::
* Using timeclock to record billable time::
+* Using XML::
@end menu
-@node Stating where money goes, Assets and Liabilities, Keeping a ledger, Keeping a ledger
+@node Stating where money goes, Assets and Liabilities, Ledger in Practice, Ledger in Practice
@section Stating where money goes
Accountants will talk of ``credits'' and ``debits'', but the meaning
@@ -2749,12 +2541,12 @@ is often different from the layman's understanding. To avoid
confusion, Ledger uses only subtractions and additions, although the
underlying intent is the same as standard accounting principles.
-Recall that every transaction will involve two or more accounts.
+Recall that every posting will involve two or more accounts.
Money is transferred from one or more accounts to one or more other
-accounts. To record the transaction, an amount is @emph{subtracted}
+accounts. To record the posting, an amount is @emph{subtracted}
from the source accounts, and @emph{added} to the target accounts.
-In order to write a Ledger entry correctly, you must determine where
+In order to write a Ledger transaction correctly, you must determine where
the money comes from and where it goes to. For example, when you are
paid a salary, you must add money to your bank account and also
subtract it from an income account:
@@ -2791,14 +2583,14 @@ place has less money now than when you started your ledger; and every
positive figure means that that account or person or place has more
money now that when you started your ledger. Make sense?
-@node Assets and Liabilities, Commodities and Currencies, Stating where money goes, Keeping a ledger
+@node Assets and Liabilities, Typical queries, Stating where money goes, Ledger in Practice
@section Assets and Liabilities
Assets are money that you have, and Liabilities are money that you
owe. ``Liabilities'' is just a more inclusive name for Debts.
An Asset is typically increased by transferring money from an Income
-account, such as when you get paid. Here is a typical entry:
+account, such as when you get paid. Here is a typical transaction:
@smallexample
2004/09/29 My Employer
@@ -2896,11 +2688,11 @@ need to track two separate things: 1) The fact that the money should
be reimbursed to you, and 2) What the expense account was, so that you
can later determine where your company is spending its money.
-This kind of transaction is best handled with mirrored transactions in
+This kind of posting is best handled with mirrored postings in
two different files, one for your personal accounts, and one for your
company accounts. But keeping them in one file involves the same
-kinds of transactions, so those are what is shown here. First, the
-personal entry, which shows the need for reimbursement:
+kinds of postings, so those are what is shown here. First, the
+personal transaction, which shows the need for reimbursement:
@smallexample
2004/09/29 Circuit City
@@ -2909,8 +2701,8 @@ personal entry, which shows the need for reimbursement:
@end smallexample
This is the same as above, except that you own Company XYZ, and are
-keeping track of its expenses in the same ledger file. This entry
-should be immediately followed by an equivalent entry, which shows the
+keeping track of its expenses in the same ledger file. This transaction
+should be immediately followed by an equivalent transaction, which shows the
kind of expense, and also notes the fact that $100.00 is now payable
to you:
@@ -2920,11 +2712,11 @@ to you:
Company XYZ:Accounts Payable:Your Name
@end smallexample
-This second entry shows that Company XYZ has just spent $100.00 on
+This second transaction shows that Company XYZ has just spent $100.00 on
software, and that this $100.00 came from Your Name, which must be
paid back.
-These two entries can also be merged, to make things a little clearer.
+These two transactions can also be merged, to make things a little clearer.
Note that all amounts must be specified now:
@smallexample
@@ -2963,12 +2755,12 @@ generate accurate reports of your company's expenditures. It is more
verbose than just paying for things with your personal assets, but it
gives you a very accurate information trail.
-The advantage to keep these doubled entries together is that they
+The advantage to keep these doubled transactions together is that they
always stay in sync. The advantage to keeping them apart is that it
-clarifies the transfer's point of view. To keep the transactions in
-separate files, just separate the two entries that were joined above.
+clarifies the transfer's point of view. To keep the postings in
+separate files, just separate the two transactions that were joined above.
For example, for both the expense and the pay-back shown above, the
-following four entries would be created. Two in your personal ledger
+following four transactions would be created. Two in your personal ledger
file:
@smallexample
@@ -3001,12 +2793,205 @@ And two in your company ledger file:
the file are children of that account. In this case it means that all
activity in the file relates to Company XYZ).
-After creating these entries, you will always know that $100.00 was
+After creating these transactions, you will always know that $100.00 was
spent using your MasterCard on behalf of Company XYZ, and that Company
XYZ spent the money on computer software and paid it back about two
weeks later.
-@node Commodities and Currencies, Accounts and Inventories, Assets and Liabilities, Keeping a ledger
+@node Typical queries, Budgeting and forecasting, Assets and Liabilities, Ledger in Practice
+@section Typical queries
+
+A query such as the following shows all expenses since last
+October, sorted by total:
+
+@example
+ledger -b "last oct" -s -S T bal ^expenses
+@end example
+
+From left to right the options mean: Show transactions since October, 2003;
+show all sub-accounts; sort by the absolute value of the total; and
+report the balance for all expenses.
+
+@subsection Reporting monthly expenses
+
+The following query makes it easy to see monthly expenses, with each
+month's expenses sorted by the amount:
+
+@example
+ledger -M --period-sort t reg ^expenses
+@end example
+
+Now, you might wonder where the money came from to pay for these
+things. To see that report, add @option{-r}, which shows the
+``related account'' postings:
+
+@example
+ledger -M --period-sort t -r reg ^expenses
+@end example
+
+But maybe this prints too much information. You might just want to
+see how much you're spending with your MasterCard. That kind of query
+requires the use of a display predicate, since the postings
+calculated must match @samp{^expenses}, while the postings
+displayed must match @samp{mastercard}. The command would be:
+
+@example
+ledger -M -r -d /mastercard/ reg ^expenses
+@end example
+
+This query says: Report monthly subtotals; report the ``related
+account'' postings; display only related postings whose
+account matches @samp{mastercard}, and base the calculation on
+postings matching @samp{^expenses}.
+
+This works just as well for report the overall total, too:
+
+@example
+ledger -s -r -d /mastercard/ reg ^expenses
+@end example
+
+The @option{-s} option subtotals all postings, just as @option{-M}
+subtotaled by the month. The running total in both cases is off,
+however, since a display expression is being used.
+
+@subsection Visualizing with Gnuplot
+
+If you have @command{Gnuplot} installed, you can graph any of the
+above register reports. The script to do this is included in the
+ledger distribution, and is named @file{scripts/report}. Install
+@file{report} anywhere along your @env{PATH}, and then use
+@command{report} instead of @command{ledger} when doing a register
+report. The only thing to keep in mind is that you must specify
+@option{-j} or @option{-J} to indicate whether Gnuplot should plot the
+amount, or the running total. For example, this command plots total
+monthly expenses made on your MasterCard.
+
+@example
+report -j -M -r -d /mastercard/ reg ^expenses
+@end example
+
+The @command{report} script is a very simple Bourne shell script, that
+passes a set of scripted commands to Gnuplot. Feel free to modify the
+script to your liking, since you may prefer histograms to line plots,
+for example.
+
+@subsubsection Typical plots
+
+Here are some useful plots:
+
+@smallexample
+report -j -M reg ^expenses # monthly expenses
+report -J reg checking # checking account balance
+report -J reg ^income ^expenses # cash flow report
+
+# net worth report, ignoring non-$ postings
+
+report -J -l "Ua>=@{\$0.01@}" reg ^assets ^liab
+
+# net worth report starting last February. the use of a display
+# predicate (-d) is needed, otherwise the balance will start at
+# zero, and thus the y-axis will not reflect the true balance
+
+report -J -l "Ua>=@{\$0.01@}" -d "d>=[last feb]" reg ^assets ^liab
+@end smallexample
+
+The last report uses both a calculation predicate (@option{-l}) and a
+display predicate (@option{-d}). The calculation predicates limits
+the report to postings whose amount is greater than $1 (which can
+only happen if the posting amount is in dollars). The display
+predicate limits the transactions @emph{displayed} to just those since last
+February, even those transactions from before then will be computed as part
+of the balance.
+
+@node Budgeting and forecasting, Commodities and Currencies, Typical queries, Ledger in Practice
+@section Budgeting and forecasting
+
+@subsection Budgeting
+
+Keeping a budget allows you to pay closer attention to your income and
+expenses, by reporting how far your actual financial activity is from
+your expectations.
+
+To start keeping a budget, put some period transactions at the top of your
+ledger file. A period transaction is almost identical to a regular transaction,
+except that it begins with a tilde and has a period expression in
+place of a payee. For example:
+
+@smallexample
+~ Monthly
+ Expenses:Rent $500.00
+ Expenses:Food $450.00
+ Expenses:Auto:Gas $120.00
+ Expenses:Insurance $150.00
+ Expenses:Phone $125.00
+ Expenses:Utilities $100.00
+ Expenses:Movies $50.00
+ Expenses $200.00 ; all other expenses
+ Assets
+
+~ Yearly
+ Expenses:Auto:Repair $500.00
+ Assets
+@end smallexample
+
+These two period transactions give the usual monthly expenses, as well as
+one typical yearly expense. For help on finding out what your average
+monthly expense is for any category, use a command like:
+
+@example
+ledger -p "this year" -MAs bal ^expenses
+@end example
+
+The reported totals are the current year's average for each account.
+
+Once these period transactions are defined, creating a budget report is as
+easy as adding @option{--budget} to the command-line. For example, a
+typical monthly expense report would be:
+
+@example
+ledger -M reg ^exp
+@end example
+
+To see the same report balanced against your budget, use:
+
+@example
+ledger --budget -M reg ^exp
+@end example
+
+A budget report includes only those accounts that appear in the
+budget. To see all expenses balanced against the budget, use
+@option{--add-budget}. You can even see only the unbudgeted expenses
+using @option{--unbudgeted}:
+
+@example
+ledger --unbudgeted -M reg ^exp
+@end example
+
+You can also use these flags with the @command{balance} command.
+
+@subsection Forecasting
+
+Sometimes it's useful to know what your finances will look like in the
+future, such as determining when an account will reach zero. Ledger
+makes this easy to do, using the same period transactions as are used for
+budgeting. An example forecast report can be generated with:
+
+@example
+ledger --forecast "T>@{\$-500.00@}" register ^assets ^liabilities
+@end example
+
+This report continues outputting postings until the running total
+is greater than $-500.00. A final posting is always output, to
+show you what the total afterwards would be.
+
+Forecasting can also be used with the balance report, but by date
+only, and not against the running total:
+
+@example
+ledger --forecast "d<[2010]" bal ^assets ^liabilities
+@end example
+
+@node Commodities and Currencies, Accounts and Inventories, Budgeting and forecasting, Ledger in Practice
@section Commodities and Currencies
Ledger makes no assumptions about the commodities you use; it only
@@ -3022,7 +3007,7 @@ specifiers:
$20.00 ; currency: twenty US dollars
40 AAPL ; commodity: 40 shares of Apple stock
60 DM ; currency: 60 Deutsch Mark
-£50 ; currency: 50 British pounds
+£50 ; currency: 50 British pounds
50 EUR ; currency: 50 Euros (or use appropriate symbol)
@end example
@@ -3104,7 +3089,7 @@ Whenever a commodity is purchased using a different commodity (such as
a share of common stock using dollars), it establishes a price for
that commodity on that day. It is also possible, by recording price
details in a ledger file, to specify other prices for commodities at
-any given time. Such price entries might look like those below:
+any given time. Such price transactions might look like those below:
@smallexample
P 2004/06/21 02:17:58 TWCUX $27.76
@@ -3126,7 +3111,7 @@ example of this is time. Whether tracked in terms of minutes, hours
or days, it should be possible to convert between the various forms.
Doing this requires the use of commodity equivalencies.
-For example, you might have the following two transactions, one which
+For example, you might have the following two postings, one which
transfers an hour of time into a @samp{Billable} account, and another
which decreases the same account by ten minutes. The resulting report
will indicate that fifty minutes remain:
@@ -3172,7 +3157,7 @@ smallest commodity is used. If a commodity could be reported in terms
of a higher commodity without resulting to a partial fraction, then
the larger commodity is used.
-@node Accounts and Inventories, Understanding Equity, Commodities and Currencies, Keeping a ledger
+@node Accounts and Inventories, Understanding Equity, Commodities and Currencies, Ledger in Practice
@section Accounts and Inventories
Since Ledger's accounts and commodity system is so flexible, you can
@@ -3198,7 +3183,7 @@ acquired them online. The only purpose for choosing one kind of
source account over another is for generate more informative reports
later on. The more you know, the better analysis you can perform.
-If you later sell some of these items to another player, the entry
+If you later sell some of these items to another player, the transaction
would look like:
@smallexample
@@ -3210,15 +3195,15 @@ would look like:
Now you've turned 2 steaks into 15 gold, courtesy of your customer,
Sturm Brightblade.
-@node Understanding Equity, Dealing with Petty Cash, Accounts and Inventories, Keeping a ledger
+@node Understanding Equity, Dealing with Petty Cash, Accounts and Inventories, Ledger in Practice
@section Understanding Equity
-The most confusing entry in any ledger will be your equity account---
+The most confusing transaction in any ledger will be your equity account---
because starting balances can't come out of nowhere.
When you first start your ledger, you will likely already have money
in some of your accounts. Let's say there's $100 in your checking
-account; then add an entry to your ledger to reflect this amount.
+account; then add a transaction to your ledger to reflect this amount.
Where will money come from? The answer: your equity.
@smallexample
@@ -3249,12 +3234,12 @@ Clear as mud? Keep thinking about it. Until you figure it out, put
@samp{-Equity} at the end of your balance command, to remove the
confusing figure from the total.
-@node Dealing with Petty Cash, Working with multiple funds and accounts, Understanding Equity, Keeping a ledger
+@node Dealing with Petty Cash, Working with multiple funds and accounts, Understanding Equity, Ledger in Practice
@section Dealing with Petty Cash
Something that stops many people from keeping a ledger at all is the
insanity of tracking small cash expenses. They rarely generate a
-receipt, and there are often a lot of small transactions, rather than
+receipt, and there are often a lot of small postings, rather than
a few large ones, as with checks.
One solution is: don't bother. Move your spending to a debit card,
@@ -3280,7 +3265,7 @@ the target account:
This way, you can still track large cash expenses, while ignoring all
of the smaller ones.
-@node Working with multiple funds and accounts, Archiving previous years, Dealing with Petty Cash, Keeping a ledger
+@node Working with multiple funds and accounts, Archiving previous years, Dealing with Petty Cash, Ledger in Practice
@section Working with multiple funds and accounts
There are situations when the accounts you're tracking are different
@@ -3319,7 +3304,7 @@ should reflect the same overall expenses and cash flow. It's simply
where the money resides that differs.
This situation can be handled one of two ways. The first is using
-virtual transactions to represent the fact that money is moving to and
+virtual postings to represent the fact that money is moving to and
from two kind of accounts at the same time:
@smallexample
@@ -3333,8 +3318,8 @@ from two kind of accounts at the same time:
[Assets:Checking] $-500.00
@end smallexample
-The use of square brackets in the second entry ensures that the
-virtual transactions balance to zero. Now money can be spent directly
+The use of square brackets in the second transaction ensures that the
+virtual postings balance to zero. Now money can be spent directly
from a fund at the same time as money is drawn from a physical
account:
@@ -3361,7 +3346,7 @@ the real accounts:
ledger --real bal
@end example
-If more asset accounts are needed as the source of a transaction, just
+If more asset accounts are needed as the source of a posting, just
list them as you would normally, for example:
@smallexample
@@ -3372,10 +3357,10 @@ list them as you would normally, for example:
(Funds:School) $-100.00
@end smallexample
-The second way of tracking funds is to use entry codes. In this
+The second way of tracking funds is to use transaction codes. In this
respect the codes become like virtual accounts that embrace the entire
-set of transactions. Basically, we are associating an entry with a
-fund by setting its code. Here are two entries that desposit money
+set of postings. Basically, we are associating a transaction with a
+fund by setting its code. Here are two transactions that desposit money
into, and spend money from, the @samp{Funds:School} fund:
@smallexample
@@ -3389,15 +3374,15 @@ into, and spend money from, the @samp{Funds:School} fund:
@end smallexample
Note how the accounts now relate only to the real accounts, and any
-balance or registers reports will reflect this. That the entries
+balance or registers reports will reflect this. That the transactions
relate to a particular fund is kept only in the code.
How does this become a fund report? By using the
@option{--code-as-payee} option, you can generate a register report
-where the payee for each transaction shows the code. Alone, this is
+where the payee for each posting shows the code. Alone, this is
not terribly interesting; but when combined with the
@option{--by-payee} option, you will now see account subtotals for any
-transactions related to a specific fund. So, to see the current
+postings related to a specific fund. So, to see the current
monetary balances of all funds, the command would be:
@smallexample
@@ -3413,10 +3398,10 @@ ledger --code-as-payee -P reg ^Expenses -- School
Both approaches yield different kinds of flexibility, depending on how
you prefer to think of your funds: as virtual accounts, or as tags
-associated with particular entries. Your own tastes will decide which
+associated with particular transactions. Your own tastes will decide which
is best for your situation.
-@node Archiving previous years, Virtual transactions, Working with multiple funds and accounts, Keeping a ledger
+@node Archiving previous years, Virtual postings, Working with multiple funds and accounts, Ledger in Practice
@section Archiving previous years
After a while, your ledger can get to be pretty large. While this
@@ -3433,7 +3418,7 @@ that make it very simple: @command{print}, and @command{equity}.
Let's take an example file, with data ranging from year 2000 until
2004. We want to archive years 2000 and 2001 to their own file,
leaving just 2003 and 2004 in the current file. So, use
-@command{print} to output all the earlier entries to a file called
+@command{print} to output all the earlier transactions to a file called
@file{ledger-old.dat}:
@smallexample
@@ -3448,7 +3433,7 @@ ledger -f ledger.dat -b 2002 print > x
mv x ledger.dat
@end example
-However, now the current file contains @emph{only} transactions from
+However, now the current file contains @emph{only} postings from
2002 onward, which will not yield accurate present-day balances,
because the net income from previous years is no longer being tallied.
To compensate for this, we must append an equity report for the old
@@ -3476,18 +3461,18 @@ any electronic statements received during the year. In the arena of
organization, just keep in mind this maxim: Do whatever keeps you
doing it.
-@node Virtual transactions, Automated transactions, Archiving previous years, Keeping a ledger
-@section Virtual transactions
+@node Virtual postings, Automated postings, Archiving previous years, Ledger in Practice
+@section Virtual postings
-A virtual transaction is when you, in your mind, see money as moving
+A virtual posting is when you, in your mind, see money as moving
to a certain place, when in reality that money has not moved at all.
There are several scenarios in which this type of tracking comes in
handy, and each of them will be discussed in detail.
-To enter a virtual transaction, surround the account name in
+To enter a virtual posting, surround the account name in
parentheses. This form of usage does not need to balance. However,
-if you want to ensure the virtual transaction balances with other
-virtual transactions in the same entry, use square brackets. For
+if you want to ensure the virtual posting balances with other
+virtual postings in the same transaction, use square brackets. For
example:
@smallexample
@@ -3513,56 +3498,56 @@ for a trip. It will appear as though the money has been moved from
the account into @samp{Savings:Trip}, although no money has actually
moved anywhere.
-When balances are displayed, virtual transactions will be factored in.
+When balances are displayed, virtual postings will be factored in.
To view balances without any virtual balances factored in, using the
@option{-R} flag, for ``reality''.
-@node Automated transactions, Using Emacs to Keep Your Ledger, Virtual transactions, Keeping a ledger
-@section Automated transactions
+@node Automated postings, Using Emacs to Keep Your Ledger, Virtual postings, Ledger in Practice
+@section Automated postings
-As a Bahá'í, I need to compute Huqúqu'lláh whenever I acquire assets.
-It is similar to tithing for Jews and Christians, or to Zakát for
-Muslims. The exact details of computing Huqúqu'lláh are somewhat
+As a Bahá'í, I need to compute Huqúqu'lláh whenever I acquire assets.
+It is similar to tithing for Jews and Christians, or to Zakát for
+Muslims. The epost details of computing Huqúqu'lláh are somewhat
complex, but if you have further interest, please consult the Web.
Ledger makes this otherwise difficult law very easy. Just set up an
-automated transaction at the top of your ledger file:
+automated posting at the top of your ledger file:
@smallexample
-; This automated entry will compute Huqúqu'lláh based on this
-; journal's transactions. Any that match will affect the
+; This automated transaction will compute Huqúqu'lláh based on this
+; journal's postings. Any that match will affect the
; Liabilities:Huququ'llah account by 19% of the value of that
-; transaction.
+; posting.
= /^(?:Income:|Expenses:(?:Business|Rent$|Furnishings|Taxes|Insurance))/
(Liabilities:Huququ'llah) 0.19
@end smallexample
-This automated transaction works by looking at each transaction in the
+This automated posting works by looking at each posting in the
ledger file. If any match the given value expression, 19% of the
-transaction's value is applied to the @samp{Liabilities:Huququ'llah}
+posting's value is applied to the @samp{Liabilities:Huququ'llah}
account. So, if $1000 is earned from @samp{Income:Salary}, $190 is
-added to @samp{Liabilities:Huqúqu'lláh}; if $1000 is spent on Rent,
-$190 is subtracted. The ultimate balance of Huqúqu'lláh reflects how
-much is owed in order to fulfill one's obligation to Huqúqu'lláh.
+added to @samp{Liabilities:Huqúqu'lláh}; if $1000 is spent on Rent,
+$190 is subtracted. The ultimate balance of Huqúqu'lláh reflects how
+much is owed in order to fulfill one's obligation to Huqúqu'lláh.
When ready to pay, just write a check to cover the amount shown in
-@samp{Liabilities:Huququ'llah}. That entry would look like:
+@samp{Liabilities:Huququ'llah}. That transaction would look like:
@smallexample
-2003/01/01 (101) Baha'i Huqúqu'lláh Trust
+2003/01/01 (101) Baha'i Huqúqu'lláh Trust
Liabilities:Huququ'llah $1,000.00
Assets:Checking
@end smallexample
-That's it. To see how much Huqúq is currently owed based on your
-ledger entries, use:
+That's it. To see how much Huqúq is currently owed based on your
+ledger transactions, use:
@example
ledger balance Liabilities:Huquq
@end example
This works fine, but omits one aspect of the law: that Huquq is only
-due once the liability exceeds the value of 19 mithqáls of gold (which
+due once the liability exceeds the value of 19 mithqáls of gold (which
is roughly 2.22 ounces). So what we want is for the liability to
appear in the balance report only when it exceeds the present day
value of 2.22 ounces of gold. This can be accomplished using the
@@ -3573,7 +3558,7 @@ ledger -Q -t "/Liab.*Huquq/?(a/P@{2.22 AU@}<=@{-1.0@}&a):a" -s bal liab
@end smallexample
With this command, the current price for gold is downloaded, and the
-Huqúqu'lláh is reported only if its value exceeds that of 2.22 ounces
+Huqúqu'lláh is reported only if its value exceeds that of 2.22 ounces
of gold. If you wish the liability to be reflected in the parent
subtotal either way, use this instead:
@@ -3582,7 +3567,7 @@ ledger -Q -T "/Liab.*Huquq/?(O/P@{2.22 AU@}<=@{-1.0@}&O):O" -s bal liab
@end smallexample
In some cases, you may wish to refer to the account of whichever
-transaction matched your automated entry's value expression. To do
+posting matched your automated transaction's value expression. To do
this, use the special account name @samp{$account}:
@smallexample
@@ -3592,10 +3577,10 @@ this, use the special account name @samp{$account}:
@end smallexample
This example causes 10% of the matching account's total to be deferred
-to the @samp{Savings} account---as a balanced virtual transaction,
+to the @samp{Savings} account---as a balanced virtual posting,
which may be excluded from reports by using @option{--real}.
-@node Using Emacs to Keep Your Ledger, Using GnuCash to Keep Your Ledger, Automated transactions, Keeping a ledger
+@node Using Emacs to Keep Your Ledger, Using GnuCash to Keep Your Ledger, Automated postings, Ledger in Practice
@section Using Emacs to Keep Your Ledger
In the Ledger tarball is an Emacs module, @file{ledger.el}. This
@@ -3618,31 +3603,31 @@ Now when you edit your ledger file, it will be in
@table @strong
@item C-c C-a
-For quickly adding new entries based on the form of older ones (see
+For quickly adding new transactions based on the form of older ones (see
previous section).
@item C-c C-c
-Toggles the ``cleared'' flag of the transaction under point.
+Toggles the ``cleared'' flag of the posting under point.
@item C-c C-d
-Delete the entry under point.
+Delete the transaction under point.
@item C-c C-r
-Reconciles an account by displaying the transactions in another
+Reconciles an account by displaying the postings in another
buffer, where simply hitting the spacebar will toggle the pending flag
-of the transaction in the ledger. Once all the appropriate
-transactions have been marked, press C-c C-c in the reconcile buffer
-to ``commit'' the reconciliation, which will mark all of the entries
+of the posting in the ledger. Once all the appropriate
+postings have been marked, press C-c C-c in the reconcile buffer
+to ``commit'' the reconciliation, which will mark all of the transactions
as cleared, and display the new cleared balance in the minibuffer.
@item C-c C-m
-Set the default month for new entries added with C-c C-a. This is
-handy if you have a large number of transactions to enter from a
+Set the default month for new transactions added with C-c C-a. This is
+handy if you have a large number of postings to enter from a
previous month.
@item C-c C-y
-Set the default year for new entries added with C-c C-a. This is
-handy if you have a large number of transactions to enter from a
+Set the default year for new transactions added with C-c C-a. This is
+handy if you have a large number of postings to enter from a
previous year.
@end table
@@ -3651,28 +3636,28 @@ available:
@table @strong
@item RET
-Visit the ledger file entry corresponding to the reconcile entry.
+Visit the ledger file transaction corresponding to the reconcile transaction.
@item C-c C-c
-Commit the reconcialation. This marks all of the marked transactions
+Commit the reconcialation. This marks all of the marked postings
as ``cleared'', saves the ledger file, and then displays the new
cleared balance.
@item C-l
-Refresh the reconcile buffer by re-reading transactions from the
+Refresh the reconcile buffer by re-reading postings from the
ledger data file.
@item SPC
-Toggle the transaction under point as cleared.
+Toggle the posting under point as cleared.
@item a
-Add a new entry to the ledger data file, and refresh the reconcile
-buffer to include its transactions (if the entry is added to the same
+Add a new transaction to the ledger data file, and refresh the reconcile
+buffer to include its postings (if the transaction is added to the same
account as the one being reconciled).
@item d
-Delete the entry related to the transaction under point. Note: This
-may result in multiple transactions being deleted.
+Delete the transaction related to the posting under point. Note: This
+may result in multiple postings being deleted.
@item n
Move to the next line.
@@ -3682,8 +3667,8 @@ Move to the previous line.
@item C-c C-r
@item r
-Attempt to auto-reconcile the transactions to the entered balance. If
-it can do so, it will mark all those transactions as pending that
+Attempt to auto-reconcile the postings to the entered balance. If
+it can do so, it will mark all those postings as pending that
would yield the specified balance.
@item C-x C-s
@@ -3698,7 +3683,7 @@ Quit the reconcile buffer.
There is also an @command{emacs} command which can be used to output
reports in a format directly @code{read}-able from Emacs Lisp.
-@node Using GnuCash to Keep Your Ledger, Using timeclock to record billable time, Using Emacs to Keep Your Ledger, Keeping a ledger
+@node Using GnuCash to Keep Your Ledger, Using timeclock to record billable time, Using Emacs to Keep Your Ledger, Ledger in Practice
@section Using GnuCash to Keep Your Ledger
The Ledger tool is fast and simple, but it offers no custom method for
@@ -3715,7 +3700,7 @@ Then again, why would anyone use a Gnome-centric, multi-megabyte
behemoth to edit their data, and only a one megabyte binary to query
it?
-@node Using timeclock to record billable time, , Using GnuCash to Keep Your Ledger, Keeping a ledger
+@node Using timeclock to record billable time, Using XML, Using GnuCash to Keep Your Ledger, Ledger in Practice
@section Using timeclock to record billable time
The timeclock tool makes it easy to track time events, like clocking
@@ -3724,7 +3709,7 @@ timelog file.
Each in/out event may have an optional description. If the ``in''
description is a ledger account name, these in/out pairs may be viewed
-as virtual transactions, adding time commodities (hours) to that
+as virtual postings, adding time commodities (hours) to that
account.
For example, the command-line version of the timeclock tool could be
@@ -3744,7 +3729,7 @@ i 2004/10/06 15:21:00 ClientOne category
o 2004/10/06 15:21:10 waited for ten seconds
@end smallexample
-Ledger parses this directly, as if it had seen the following entry:
+Ledger parses this directly, as if it had seen the following transaction:
@smallexample
2004/10/06 category
@@ -3762,7 +3747,7 @@ to accounts receivable:
ClientOne -0.00277h @@ $35.00
@end smallexample
-The above transaction converts the clocked time into an invoice for
+The above posting converts the clocked time into an invoice for
the time spent, at an hourly rate of $35. Once the invoice is paid,
the money is deposited from the receivable account into a checking
account:
@@ -3777,7 +3762,7 @@ And now the time spent has been turned into hard cash in the checking
account.
The advantage to using timeclock and invoicing to bill time is that
-you will always know, by looking at the balance report, exactly how
+you will always know, by looking at the balance report, epostly how
much unbilled and unpaid time you've spent working for any particular
client.
@@ -3795,7 +3780,7 @@ accounting ledger, with the attached prefix @samp{Billable}:
!include /home/johnw/.timelog
!end
-; Here follows this fiscal year's transactions for the company.
+; Here follows this fiscal year's postings for the company.
2004/11/01 (INV#1) ClientOne, Inc.
Receivable:ClientOne $0.10
@@ -3806,60 +3791,60 @@ accounting ledger, with the attached prefix @samp{Billable}:
Receivable:ClientOne
@end smallexample
-@node Using XML, , Keeping a ledger, Top
-@chapter Using XML
+@node Using XML, , Using timeclock to record billable time, Ledger in Practice
+@section Using XML
By default, Ledger uses a human-readable data format, and displays its
reports in a manner meant to be read on screen. For the purpose of
writing tools which use Ledger, however, it is possible to read and
-display data using XML. This chapter documents that format.
+display data using XML. This section documents that format.
The general format used for Ledger data is:
@smallexample
<?xml version="1.0"?>
<ledger>
- <entry>...</entry>
- <entry>...</entry>
- <entry>...</entry>...
+ <xact>...</xact>
+ <xact>...</xact>
+ <xact>...</xact>...
</ledger>
@end smallexample
The data stream is enclosed in a @samp{ledger} tag, which contains a
-series of one or more entries. Each @samp{entry} describes the entry
-and contains a series of one or more transactions:
+series of one or more transactions. Each @samp{xact} describes the transaction
+and contains a series of one or more postings:
@smallexample
-<entry>
+<xact>
<en:date>2004/03/01</en:date>
<en:cleared/>
<en:code>100</en:code>
<en:payee>John Wiegley</en:payee>
- <en:transactions>
- <transaction>...</transaction>
- <transaction>...</transaction>
- <transaction>...</transaction>...
- </en:transactions>
-</entry>
+ <en:postings>
+ <posting>...</posting>
+ <posting>...</posting>
+ <posting>...</posting>...
+ </en:postings>
+</xact>
@end smallexample
The date format for @samp{en:date} is always @samp{YYYY/MM/DD}. The
@samp{en:cleared} tag is optional, and indicates whether the
-transaction has been cleared or not. There is also an
-@samp{en:pending} tag, for marking pending transactions. The
+posting has been cleared or not. There is also an
+@samp{en:pending} tag, for marking pending postings. The
@samp{en:code} and @samp{en:payee} tags both contain whatever text the
user wishes.
-After the initial entry data, there must follow a set of transactions
-marked with @samp{en:transactions}. Typically these transactions will
+After the initial transaction data, there must follow a set of postings
+marked with @samp{en:postings}. Typically these postings will
all balance each other, but if not they will be automatically balanced
into an account named @samp{<Unknown>}.
-Within the @samp{en:transactions} tag is a series of one or more
-@samp{transaction}'s, which have the following form:
+Within the @samp{en:postings} tag is a series of one or more
+@samp{posting}'s, which have the following form:
@smallexample
-<transaction>
+<posting>
<tr:account>Expenses:Computer:Hardware</tr:account>
<tr:amount>
<value type="amount">
@@ -3869,16 +3854,16 @@ Within the @samp{en:transactions} tag is a series of one or more
</amount>
</value>
</tr:amount>
-</transaction>
+</posting>
@end smallexample
-This is a basic transaction. It may also be begin with
+This is a basic posting. It may also be begin with
@samp{tr:virtual} and/or @samp{tr:generated} tags, to indicate virtual
-and auto-generated transactions. Then follows the @samp{tr:account}
-tag, which contains the full name of the account the transaction is
+and auto-generated postings. Then follows the @samp{tr:account}
+tag, which contains the full name of the account the posting is
related to. Colons separate parent from child in an account name.
-Lastly follows the amount of the transaction, indicated by
+Lastly follows the amount of the posting, indicated by
@samp{tr:amount}. Within this tag is a @samp{value} tag, of which
there are four different kinds, each with its own format:
@@ -3955,7 +3940,171 @@ example:
That is the extent of the XML data format used by Ledger. It will
output such data if the @command{xml} command is used, and can read
-the same data as long as the @file{expat} library was available
-when Ledger was built.
+the same data.
+
+@chapter Random things
+
+Whenever a commodity is exchanged for another in a posting, one of the
+two is considered @emph{primary}, and the other secondary.
+Primariness of a commodity is remembered, since the @option{--market}
+option only renders balances into secondary commodities, never
+primaries. To render primaries, use the @option{--exchange=COMMODITY}
+option.
+
+In all of the following examples, the P commodity is considered primary
+and the S is secondary (the P at the beginning of the line indicates a
+price-setting directive):
+
+@smallexample
+2009/01/01 Sample 1a
+ Assets:Brokerage:Stocks 100 S
+ Assets:Brokerage:Cash -100 P
+
+P 2009/01/15 00:00:00 S 2 P
+
+2009/02/01 Sample 2a
+ Assets:Brokerage:Stocks 100 S @ 1 P
+ Assets:Brokerage:Cash
+
+P 2009/02/01 00:00:00 S 4 P
+
+2009/03/01 Sample 3a
+ Assets:Brokerage:Stocks 100 S @@ 100 P
+ Assets:Brokerage:Cash
+
+P 2009/03/01 00:00:00 S 8 P
+
+2009/04/01 Sample 4a
+ Assets:Brokerage:Cash 100 P
+ Assets:Brokerage:Stocks -100 S @{1 P@}
+
+P 2009/04/01 00:00:00 S 16 P
+@end smallexample
+
+@chapter Anatomy of a journal file
+
+Everything begins with a journal file---the anatomy of which is covered
+in detail in chapter one. To review: a @emph{journal} contains one or
+more @emph{transactions}, each of which refers to two or more
+@emph{postings}. A @emph{posting} specifies that a given
+@emph{amount} is added to, or subtracted from, an @emph{account}.
+(@emph{Accounts} may be nested hierarchically by separating the elements
+using a colon). Lastly, an @emph{amount} is a figure representing a
+given @emph{quantity} of a @emph{commodity}. Here follows a review of
+these terms, which are all used extensively throughout this chapter:
+
+@table @emph
+@item journal
+A journal is a data file containing a series of transactions.
+
+@item transaction
+a transaction relates a group of two or more postings, with the absolute
+constraint that the total sum of a transaction's postings must equal
+zero. That is, every transaction in a journal must @emph{balance} to zero.
+
+@item posting
+Postings record how commodities are moved between accounts. If you
+spent money on a movie ticket, for example, such a transaction would have two
+postings: One to show how the money was taken from your wallet, and
+another to show how it was applied to your movie expenses.
+
+@item account
+An account
+
+@item amount
+
+@item quantity
+
+@item commodity
+@end table
+
+@chapter Example accounting practices
+
+@chapter Generating useful reports
+
+Once you have a journal file representing a recent history of your
+finances, the next step is to generate reports in order to give richer
+meaning to this data. For example: Where do you spend your money? Do
+you have enough to cover upcoming expenses? Are you creating or losing
+net worth? Are your investment performing well? All of these questions
+can be answered easily with Ledger---if you know how to ask them.
+
+Preparing complex reports is not a simple task, but neither is it a
+difficult one. All that's required is a proper understanding of how
+Ledger views your data, and how it prepares it for reporting.
+
+After Ledger reads a journal file, it creates an in-memory
+representation reflecting the order and composition of those transactions.
+
+@chapter Value expressions
+
+@chapter Format strings
+
+@chapter Extensions in Python
+
+@chapter The design of Ledger
+
+The following sections discuss how Ledger is architected, from the
+ground up, and will show how to use the various parts of the Ledger
+library from your own scripts. Ledger essentially follows five steps in
+reporting data to the user:
+
+@enumerate
+@item Parse journal file into an internal representation
+@item Perform any implied math within the journal file
+@item ``Face'' this internal representation as a virtual document
+@item Apply a series of transforms to the virtual document
+@item Display the virtual document using a formatting command
+@end enumerate
+
+The calculations in step two are specified by the user, such as when a
+posting's value might contain mathematical operators. The
+calculations in step four are implied in the transformations, for
+example when the @option{--average} option is used.
+
+At the core, however, Ledger is basically a sophisticated calculator
+with special knowledge about commoditized values. It knows what you
+mean if you add ten dollars to twenty euros, and later ask for the
+balance of that particular account. So it follows that first we must
+discuss how Ledger deals with math, and from there move on to describing
+how the steps above are achieved.
+
+@section Numerics
+
+@subsection Basic amounts
+
+The most fundamental type in Ledger is the amount, which may or may
+not have a commodity attached to it. First, we'll deal with the bare
+case, just to show how the amount type works. In C++, most all of
+Ledger's internal types end in @code{_t}; in Python, the same type
+name is used, but the @code{_t} suffix is dropped. Examples of usage
+in both languages will be presented throughout.
+
+
+
+amount_t
+commodity_t
+updater_t
+datetime_t
+balance_t
+balance_pair_t
+value_t
+valexpr_t
+format_t
+mask_t
+
+@section Journal Representation
+
+journal_t
+account_t
+xact_t
+post_t
+parser_t
+
+@section Reporting
+
+@section Terminal Interface
+
+@section General Utility
@bye
diff --git a/doc/sample.dat b/doc/sample.dat
new file mode 100644
index 00000000..12ac4cb4
--- /dev/null
+++ b/doc/sample.dat
@@ -0,0 +1,54 @@
+; -*- ledger -*-
+
+N $
+
+= /^Expenses:Books/
+ (Liabilities:Taxes) -0.10
+
+~ Monthly
+ Assets:Bank:Checking $500.00
+ Income:Salary
+
+~ Yearly
+ Expenses:Donations $100.00
+ Assets:Bank:Checking
+
+2004/05/01 * Checking balance
+ Assets:Bank:Checking $1,000.00
+ Equity:Opening Balances
+
+2004/05/03=2004/05/01 * Investment balance
+ Assets:Brokerage 50 AAPL @ $30.00
+ Equity:Opening Balances
+
+2004/05/14 * Páy dày
+ Assets:Bank:Checking 500.00€
+ Income:Salary
+
+2004/05/14 * Another dày in which there is Páying
+ Asséts:Bánk:Chécking:Asséts:Bánk:Chécking $500.00
+ Income:Salary
+
+2004/05/14 * Another dày in which there is Páying
+ РуÑÑкий Ñзык:Ðктивы:РуÑÑкий Ñзык:РуÑÑкий Ñзык $1000.00
+ Income:Salary
+
+tag foo
+
+2004/05/27 Book Store
+ Expenses:Books $20.00
+ Expenses:Cards $40.00
+ Expenses:Docs $30.00
+ Liabilities:MasterCard
+
+end tag
+
+2004/05/27 (100) Credit card company
+ ; This is an xact note!
+ ; Sample: Value
+ Liabilities:MasterCard $20.00
+ ; This is a posting note!
+ ; Sample: Another Value
+ ; :MyTag:
+ Assets:Bank:Checking
+ ; :AnotherTag:
diff --git a/emacs.cc b/emacs.cc
deleted file mode 100644
index 7551b37c..00000000
--- a/emacs.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "emacs.h"
-
-namespace ledger {
-
-void format_emacs_transactions::write_entry(entry_t& entry)
-{
- int idx = entry.src_idx;
- for (strings_list::iterator i = entry.journal->sources.begin();
- i != entry.journal->sources.end();
- i++)
- if (! idx--) {
- out << "\"" << *i << "\" ";
- break;
- }
-
- out << ((unsigned long)entry.beg_line) << " ";
-
- std::time_t date = entry.date().when;
- out << "(" << (date / 65536) << " " << (date % 65536) << " 0) ";
-
- if (entry.code.empty())
- out << "nil ";
- else
- out << "\"" << entry.code << "\" ";
-
- if (entry.payee.empty())
- out << "nil";
- else
- out << "\"" << entry.payee << "\"";
-
- out << "\n";
-}
-
-void format_emacs_transactions::operator()(transaction_t& xact)
-{
- if (! transaction_has_xdata(xact) ||
- ! (transaction_xdata_(xact).dflags & TRANSACTION_DISPLAYED)) {
- if (! last_entry) {
- out << "((";
- write_entry(*xact.entry);
- }
- else if (xact.entry != last_entry) {
- out << ")\n (";
- write_entry(*xact.entry);
- }
- else {
- out << "\n";
- }
-
- out << " (" << ((unsigned long)xact.beg_line) << " ";
- out << "\"" << xact_account(xact)->fullname() << "\" \""
- << xact.amount << "\"";
-
- switch (xact.state) {
- case transaction_t::CLEARED:
- out << " t";
- break;
- case transaction_t::PENDING:
- out << " pending";
- break;
- default:
- out << " nil";
- break;
- }
-
- if (xact.cost)
- out << " \"" << *xact.cost << "\"";
- else if (! xact.note.empty())
- out << " nil";
- if (! xact.note.empty())
- out << " \"" << xact.note << "\"";
- out << ")";
-
- last_entry = xact.entry;
-
- transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED;
- }
-}
-
-} // namespace ledger
diff --git a/emacs.h b/emacs.h
deleted file mode 100644
index ea58bad8..00000000
--- a/emacs.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef _EMACS_H
-#define _EMACS_H
-
-#include "journal.h"
-#include "format.h"
-
-namespace ledger {
-
-class format_emacs_transactions : public item_handler<transaction_t>
-{
- protected:
- std::ostream& out;
- entry_t * last_entry;
-
- public:
- format_emacs_transactions(std::ostream& _out)
- : out(_out), last_entry(NULL) {}
-
- virtual void write_entry(entry_t& entry);
- virtual void flush() {
- if (last_entry)
- out << "))\n";
- out.flush();
- }
- virtual void operator()(transaction_t& xact);
-};
-
-} // namespace ledger
-
-#endif // _REPORT_H
diff --git a/error.h b/error.h
deleted file mode 100644
index 7f77db0f..00000000
--- a/error.h
+++ /dev/null
@@ -1,125 +0,0 @@
-#ifndef _ERROR_H
-#define _ERROR_H
-
-#include <exception>
-#include <string>
-#include <cstring>
-#include <sstream>
-#include <list>
-
-class error_context
-{
- public:
- std::string desc;
-
- error_context(const std::string& _desc) throw() : desc(_desc) {}
- virtual ~error_context() throw() {}
- virtual void describe(std::ostream& out) const throw() {
- if (! desc.empty())
- out << desc << std::endl;
- }
-};
-
-class file_context : public error_context
-{
- protected:
- std::string file;
- unsigned long line;
- public:
- file_context(const std::string& _file, unsigned long _line,
- const std::string& desc = "") throw()
- : error_context(desc), file(_file), line(_line) {}
- virtual ~file_context() throw() {}
-
- virtual void describe(std::ostream& out) const throw() {
- if (! desc.empty())
- out << desc << " ";
-
- out << "\"" << file << "\", line " << line << ": ";
- }
-};
-
-class line_context : public error_context {
- public:
- std::string line;
- long pos;
-
- line_context(const std::string& _line, long _pos,
- const std::string& desc = "") throw()
- : error_context(desc), line(_line), pos(_pos) {}
- virtual ~line_context() throw() {}
-
- virtual void describe(std::ostream& out) const throw() {
- if (! desc.empty())
- out << desc << std::endl;
-
- out << " " << line << std::endl << " ";
- long idx = pos < 0 ? line.length() - 1 : pos;
- for (int i = 0; i < idx; i++)
- out << " ";
- out << "^" << std::endl;
- }
-};
-
-//////////////////////////////////////////////////////////////////////
-
-class str_exception : public std::exception {
- protected:
- std::string reason;
- public:
- std::list<error_context *> context;
-
- str_exception(const std::string& _reason,
- error_context * ctxt = NULL) throw()
- : reason(_reason) {
- if (ctxt)
- context.push_back(ctxt);
- }
-
- virtual ~str_exception() throw() {
- for (std::list<error_context *>::iterator i = context.begin();
- i != context.end();
- i++)
- delete *i;
- }
-
- virtual void reveal_context(std::ostream& out,
- const std::string& kind) const throw() {
- for (std::list<error_context *>::const_reverse_iterator i =
- context.rbegin();
- i != context.rend();
- i++) {
- std::list<error_context *>::const_reverse_iterator x = i;
- if (++x == context.rend())
- out << kind << ": ";
- (*i)->describe(out);
- }
- }
-
- virtual const char* what() const throw() {
- return reason.c_str();
- }
-};
-
-class error : public str_exception {
- public:
- error(const std::string& reason, error_context * ctxt = NULL) throw()
- : str_exception(reason, ctxt) {}
- virtual ~error() throw() {}
-};
-
-class fatal : public str_exception {
- public:
- fatal(const std::string& reason, error_context * ctxt = NULL) throw()
- : str_exception(reason, ctxt) {}
- virtual ~fatal() throw() {}
-};
-
-class fatal_assert : public fatal {
- public:
- fatal_assert(const std::string& reason, error_context * ctxt = NULL) throw()
- : fatal(std::string("assertion failed '") + reason + "'", ctxt) {}
- virtual ~fatal_assert() throw() {}
-};
-
-#endif // _ERROR_H
diff --git a/fdstream.hpp b/fdstream.hpp
deleted file mode 100644
index a74a5781..00000000
--- a/fdstream.hpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/* The following code declares classes to read from and write to
- * file descriptore or file handles.
- *
- * See
- * http://www.josuttis.com/cppcode
- * for details and the latest version.
- *
- * - open:
- * - integrating BUFSIZ on some systems?
- * - optimized reading of multiple characters
- * - stream for reading AND writing
- * - i18n
- *
- * (C) Copyright Nicolai M. Josuttis 2001.
- * Permission to copy, use, modify, sell and distribute this software
- * is granted provided this copyright notice appears in all copies.
- * This software is provided "as is" without express or implied
- * warranty, and with no claim as to its suitability for any purpose.
- *
- * Version: Jul 28, 2002
- * History:
- * Jul 28, 2002: bugfix memcpy() => memmove()
- * fdinbuf::underflow(): cast for return statements
- * Aug 05, 2001: first public version
- */
-#ifndef BOOST_FDSTREAM_HPP
-#define BOOST_FDSTREAM_HPP
-
-#include <istream>
-#include <ostream>
-#include <streambuf>
-// for EOF:
-#include <cstdio>
-// for memmove():
-#include <cstring>
-
-
-// low-level read and write functions
-#ifdef _MSC_VER
-# include <io.h>
-#else
-# include <unistd.h>
-//extern "C" {
-// int write (int fd, const char* buf, int num);
-// int read (int fd, char* buf, int num);
-//}
-#endif
-
-
-// BEGIN namespace BOOST
-namespace boost {
-
-
-/************************************************************
- * fdostream
- * - a stream that writes on a file descriptor
- ************************************************************/
-
-
-class fdoutbuf : public std::streambuf {
- protected:
- int fd; // file descriptor
- public:
- // constructor
- fdoutbuf (int _fd) : fd(_fd) {
- }
- protected:
- // write one character
- virtual int_type overflow (int_type c) {
- if (c != EOF) {
- char z = c;
- if (write (fd, &z, 1) != 1) {
- return EOF;
- }
- }
- return c;
- }
- // write multiple characters
- virtual
- std::streamsize xsputn (const char* s,
- std::streamsize num) {
- return write(fd,s,num);
- }
-};
-
-class fdostream : public std::ostream {
- protected:
- fdoutbuf buf;
- public:
- fdostream (int fd) : std::ostream(0), buf(fd) {
- rdbuf(&buf);
- }
-};
-
-
-/************************************************************
- * fdistream
- * - a stream that reads on a file descriptor
- ************************************************************/
-
-class fdinbuf : public std::streambuf {
- protected:
- int fd; // file descriptor
- protected:
- /* data buffer:
- * - at most, pbSize characters in putback area plus
- * - at most, bufSize characters in ordinary read buffer
- */
- static const int pbSize = 4; // size of putback area
- static const int bufSize = 1024; // size of the data buffer
- char buffer[bufSize+pbSize]; // data buffer
-
- public:
- /* constructor
- * - initialize file descriptor
- * - initialize empty data buffer
- * - no putback area
- * => force underflow()
- */
- fdinbuf (int _fd) : fd(_fd) {
- setg (buffer+pbSize, // beginning of putback area
- buffer+pbSize, // read position
- buffer+pbSize); // end position
- }
-
- protected:
- // insert new characters into the buffer
- virtual int_type underflow () {
-#ifndef _MSC_VER
- using std::memmove;
-#endif
-
- // is read position before end of buffer?
- if (gptr() < egptr()) {
- return traits_type::to_int_type(*gptr());
- }
-
- /* process size of putback area
- * - use number of characters read
- * - but at most size of putback area
- */
- int numPutback;
- numPutback = gptr() - eback();
- if (numPutback > pbSize) {
- numPutback = pbSize;
- }
-
- /* copy up to pbSize characters previously read into
- * the putback area
- */
- memmove (buffer+(pbSize-numPutback), gptr()-numPutback,
- numPutback);
-
- // read at most bufSize new characters
- int num;
- num = read (fd, buffer+pbSize, bufSize);
- if (num <= 0) {
- // ERROR or EOF
- return EOF;
- }
-
- // reset buffer pointers
- setg (buffer+(pbSize-numPutback), // beginning of putback area
- buffer+pbSize, // read position
- buffer+pbSize+num); // end of buffer
-
- // return next character
- return traits_type::to_int_type(*gptr());
- }
-};
-
-class fdistream : public std::istream {
- protected:
- fdinbuf buf;
- public:
- fdistream (int fd) : std::istream(0), buf(fd) {
- rdbuf(&buf);
- }
-};
-
-
-} // END namespace boost
-
-#endif /*BOOST_FDSTREAM_HPP*/
diff --git a/format.cc b/format.cc
deleted file mode 100644
index cb890926..00000000
--- a/format.cc
+++ /dev/null
@@ -1,985 +0,0 @@
-#include "format.h"
-#include "error.h"
-#include "util.h"
-
-#include <cstdlib>
-
-namespace ledger {
-
-format_t::elision_style_t format_t::elision_style = ABBREVIATE;
-int format_t::abbrev_length = 2;
-
-bool format_t::ansi_codes = false;
-bool format_t::ansi_invert = false;
-
-std::string format_t::truncate(const std::string& str, unsigned int width,
- const bool is_account)
-{
- const int len = str.length();
- if (len <= width)
- return str;
-
- assert(width < 4095);
-
- char buf[4096];
-
- switch (elision_style) {
- case TRUNCATE_LEADING:
- // This method truncates at the beginning.
- std::strncpy(buf, str.c_str() + (len - width), width);
- buf[0] = '.';
- buf[1] = '.';
- break;
-
- case TRUNCATE_MIDDLE:
- // This method truncates in the middle.
- std::strncpy(buf, str.c_str(), width / 2);
- std::strncpy(buf + width / 2,
- str.c_str() + (len - (width / 2 + width % 2)),
- width / 2 + width % 2);
- buf[width / 2 - 1] = '.';
- buf[width / 2] = '.';
- break;
-
- case ABBREVIATE:
- if (is_account) {
- std::list<std::string> parts;
- std::string::size_type beg = 0;
- for (std::string::size_type pos = str.find(':');
- pos != std::string::npos;
- beg = pos + 1, pos = str.find(':', beg))
- parts.push_back(std::string(str, beg, pos - beg));
- parts.push_back(std::string(str, beg));
-
- std::string result;
- int newlen = len;
- for (std::list<std::string>::iterator i = parts.begin();
- i != parts.end();
- i++) {
- // Don't contract the last element
- std::list<std::string>::iterator x = i;
- if (++x == parts.end()) {
- result += *i;
- break;
- }
-
- if (newlen > width) {
- result += std::string(*i, 0, abbrev_length);
- result += ":";
- newlen -= (*i).length() - abbrev_length;
- } else {
- result += *i;
- result += ":";
- }
- }
-
- if (newlen > width) {
- // Even abbreviated its too big to show the last account, so
- // abbreviate all but the last and truncate at the beginning.
- std::strncpy(buf, result.c_str() + (result.length() - width), width);
- buf[0] = '.';
- buf[1] = '.';
- } else {
- std::strcpy(buf, result.c_str());
- }
- break;
- }
- // fall through...
-
- case TRUNCATE_TRAILING:
- // This method truncates at the end (the default).
- std::strncpy(buf, str.c_str(), width - 2);
- buf[width - 2] = '.';
- buf[width - 1] = '.';
- break;
- }
- buf[width] = '\0';
-
- return buf;
-}
-
-std::string partial_account_name(const account_t& account)
-{
- std::string name;
-
- for (const account_t * acct = &account;
- acct && acct->parent;
- acct = acct->parent) {
- if (account_has_xdata(*acct) &&
- account_xdata_(*acct).dflags & ACCOUNT_DISPLAYED)
- break;
-
- if (name.empty())
- name = acct->name;
- else
- name = acct->name + ":" + name;
- }
-
- return name;
-}
-
-element_t * format_t::parse_elements(const std::string& fmt)
-{
- std::auto_ptr<element_t> result;
-
- element_t * current = NULL;
-
- char buf[1024];
- char * q = buf;
-
- for (const char * p = fmt.c_str(); *p; p++) {
- if (*p != '%' && *p != '\\') {
- *q++ = *p;
- continue;
- }
-
- if (! result.get()) {
- result.reset(new element_t);
- current = result.get();
- } else {
- current->next = new element_t;
- current = current->next;
- }
-
- if (q != buf) {
- current->type = element_t::STRING;
- current->chars = std::string(buf, q);
- q = buf;
-
- current->next = new element_t;
- current = current->next;
- }
-
- if (*p == '\\') {
- p++;
- current->type = element_t::STRING;
- switch (*p) {
- case 'b': current->chars = "\b"; break;
- case 'f': current->chars = "\f"; break;
- case 'n': current->chars = "\n"; break;
- case 'r': current->chars = "\r"; break;
- case 't': current->chars = "\t"; break;
- case 'v': current->chars = "\v"; break;
- }
- continue;
- }
-
- ++p;
- while (*p == '!' || *p == '-') {
- switch (*p) {
- case '-':
- current->flags |= ELEMENT_ALIGN_LEFT;
- break;
- case '!':
- current->flags |= ELEMENT_HIGHLIGHT;
- break;
- }
- ++p;
- }
-
- int num = 0;
- while (*p && std::isdigit(*p)) {
- num *= 10;
- num += *p++ - '0';
- }
- current->min_width = num;
-
- if (*p == '.') {
- ++p;
- num = 0;
- while (*p && std::isdigit(*p)) {
- num *= 10;
- num += *p++ - '0';
- }
- current->max_width = num;
- if (current->min_width == 0)
- current->min_width = current->max_width;
- }
-
- switch (*p) {
- case '%':
- current->type = element_t::STRING;
- current->chars = "%";
- break;
-
- case '(': {
- ++p;
- const char * b = p;
- int depth = 1;
- while (*p) {
- if (*p == ')' && --depth == 0)
- break;
- else if (*p == '(')
- ++depth;
- p++;
- }
- if (*p != ')')
- throw new format_error("Missing ')'");
-
- current->type = element_t::VALUE_EXPR;
-
- assert(! current->val_expr);
- current->val_expr = std::string(b, p);
- break;
- }
-
- case '[': {
- ++p;
- const char * b = p;
- int depth = 1;
- while (*p) {
- if (*p == ']' && --depth == 0)
- break;
- else if (*p == '[')
- ++depth;
- p++;
- }
- if (*p != ']')
- throw new format_error("Missing ']'");
-
- current->type = element_t::DATE_STRING;
- current->chars = std::string(b, p);
- break;
- }
-
- case 'x':
- switch (*++p) {
- case 'B': current->type = element_t::XACT_BEG_POS; break;
- case 'b': current->type = element_t::XACT_BEG_LINE; break;
- case 'E': current->type = element_t::XACT_END_POS; break;
- case 'e': current->type = element_t::XACT_END_LINE; break;
- case '\0':
- goto END;
- }
- break;
-
- case 'd':
- current->type = element_t::COMPLETE_DATE_STRING;
- current->chars = datetime_t::output_format;
- break;
- case 'D':
- current->type = element_t::DATE_STRING;
- current->chars = datetime_t::output_format;
- break;
-
- case 'S': current->type = element_t::SOURCE; break;
- case 'B': current->type = element_t::ENTRY_BEG_POS; break;
- case 'b': current->type = element_t::ENTRY_BEG_LINE; break;
- case 'E': current->type = element_t::ENTRY_END_POS; break;
- case 'e': current->type = element_t::ENTRY_END_LINE; break;
- case 'X': current->type = element_t::CLEARED; break;
- case 'Y': current->type = element_t::ENTRY_CLEARED; break;
- case 'C': current->type = element_t::CODE; break;
- case 'P': current->type = element_t::PAYEE; break;
- case 'W': current->type = element_t::OPT_ACCOUNT; break;
- case 'a': current->type = element_t::ACCOUNT_NAME; break;
- case 'A': current->type = element_t::ACCOUNT_FULLNAME; break;
- case 't': current->type = element_t::AMOUNT; break;
- case 'o': current->type = element_t::OPT_AMOUNT; break;
- case 'T': current->type = element_t::TOTAL; break;
- case 'N': current->type = element_t::NOTE; break;
- case 'n': current->type = element_t::OPT_NOTE; break;
- case '|': current->type = element_t::SPACER; break;
- case '_': current->type = element_t::DEPTH_SPACER; break;
- }
- }
-
- END:
- if (q != buf) {
- if (! result.get()) {
- result.reset(new element_t);
- current = result.get();
- } else {
- current->next = new element_t;
- current = current->next;
- }
- current->type = element_t::STRING;
- current->chars = std::string(buf, q);
- }
-
- return result.release();
-}
-
-namespace {
- inline void mark_red(std::ostream& out, const element_t * elem) {
- out.setf(std::ios::left);
- out.width(0);
- out << "\e[31m";
-
- if (elem->flags & ELEMENT_ALIGN_LEFT)
- out << std::left;
- else
- out << std::right;
-
- if (elem->min_width > 0)
- out.width(elem->min_width);
- }
-
- inline void mark_plain(std::ostream& out) {
- out << "\e[0m";
- }
-}
-
-void format_t::format(std::ostream& out_str, const details_t& details) const
-{
- for (const element_t * elem = elements; elem; elem = elem->next) {
- std::ostringstream out;
- std::string name;
- bool ignore_max_width = false;
-
- if (elem->flags & ELEMENT_ALIGN_LEFT)
- out << std::left;
- else
- out << std::right;
-
- if (elem->min_width > 0)
- out.width(elem->min_width);
-
- switch (elem->type) {
- case element_t::STRING:
- out << elem->chars;
- break;
-
- case element_t::AMOUNT:
- case element_t::TOTAL:
- case element_t::VALUE_EXPR: {
- value_expr calc;
- switch (elem->type) {
- case element_t::AMOUNT: calc = amount_expr; break;
- case element_t::TOTAL: calc = total_expr; break;
- case element_t::VALUE_EXPR: calc = elem->val_expr; break;
- default:
- assert(0);
- break;
- }
- if (! calc)
- break;
-
- value_t value;
- balance_t * bal = NULL;
-
- calc->compute(value, details);
-
- if (! amount_t::keep_price ||
- ! amount_t::keep_date ||
- ! amount_t::keep_tag) {
- switch (value.type) {
- case value_t::AMOUNT:
- case value_t::BALANCE:
- case value_t::BALANCE_PAIR:
- value = value.strip_annotations();
- break;
- default:
- break;
- }
- }
-
- bool highlighted = false;
-
- switch (value.type) {
- case value_t::BOOLEAN:
- out << (*((bool *) value.data) ? "true" : "false");
- break;
-
- case value_t::INTEGER:
- if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
- if (ansi_invert) {
- if (*((long *) value.data) > 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- } else {
- if (*((long *) value.data) < 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- }
- }
- out << *((long *) value.data);
- break;
-
- case value_t::DATETIME:
- out << *((datetime_t *) value.data);
- break;
-
- case value_t::AMOUNT:
- if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
- if (ansi_invert) {
- if (*((amount_t *) value.data) > 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- } else {
- if (*((amount_t *) value.data) < 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- }
- }
- out << *((amount_t *) value.data);
- break;
-
- case value_t::BALANCE:
- bal = (balance_t *) value.data;
- // fall through...
-
- case value_t::BALANCE_PAIR:
- if (! bal)
- bal = &((balance_pair_t *) value.data)->quantity;
-
- if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
- if (ansi_invert) {
- if (*bal > 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- } else {
- if (*bal < 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- }
- }
- bal->write(out, elem->min_width,
- (elem->max_width > 0 ?
- elem->max_width : elem->min_width));
-
- ignore_max_width = true;
- break;
- default:
- assert(0);
- break;
- }
-
- if (highlighted)
- mark_plain(out);
- break;
- }
-
- case element_t::OPT_AMOUNT:
- if (details.xact) {
- std::string disp;
- bool use_disp = false;
-
- if (details.xact->cost && details.xact->amount) {
- std::ostringstream stream;
- if (! details.xact->amount_expr.expr.empty())
- stream << details.xact->amount_expr.expr;
- else
- stream << details.xact->amount.strip_annotations();
-
- if (! details.xact->cost_expr.empty())
- stream << details.xact->cost_expr;
- else
- stream << " @ " << amount_t(*details.xact->cost /
- details.xact->amount).unround();
- disp = stream.str();
- use_disp = true;
- }
- else if (details.entry) {
- unsigned int xacts_count = 0;
- transaction_t * first = NULL;
- transaction_t * last = NULL;
-
- for (transactions_list::const_iterator i
- = details.entry->transactions.begin();
- i != details.entry->transactions.end();
- i++)
- if (transaction_has_xdata(**i) &&
- transaction_xdata_(**i).dflags & TRANSACTION_TO_DISPLAY) {
- xacts_count++;
- if (! first)
- first = *i;
- last = *i;
- }
-
- use_disp = (xacts_count == 2 && details.xact == last &&
- first->amount == - last->amount);
- }
-
- if (! use_disp) {
- if (! details.xact->amount_expr.expr.empty())
- out << details.xact->amount_expr.expr;
- else
- out << details.xact->amount.strip_annotations();
- } else {
- out << disp;
- }
- }
- break;
-
- case element_t::SOURCE:
- if (details.entry && details.entry->journal) {
- int idx = details.entry->src_idx;
- for (strings_list::iterator i = details.entry->journal->sources.begin();
- i != details.entry->journal->sources.end();
- i++)
- if (! idx--) {
- out << *i;
- break;
- }
- }
- break;
-
- case element_t::ENTRY_BEG_POS:
- if (details.entry)
- out << (unsigned long)details.entry->beg_pos;
- break;
-
- case element_t::ENTRY_BEG_LINE:
- if (details.entry)
- out << details.entry->beg_line;
- break;
-
- case element_t::ENTRY_END_POS:
- if (details.entry)
- out << (unsigned long)details.entry->end_pos;
- break;
-
- case element_t::ENTRY_END_LINE:
- if (details.entry)
- out << details.entry->end_line;
- break;
-
- case element_t::XACT_BEG_POS:
- if (details.xact)
- out << (unsigned long)details.xact->beg_pos;
- break;
-
- case element_t::XACT_BEG_LINE:
- if (details.xact)
- out << details.xact->beg_line;
- break;
-
- case element_t::XACT_END_POS:
- if (details.xact)
- out << (unsigned long)details.xact->end_pos;
- break;
-
- case element_t::XACT_END_LINE:
- if (details.xact)
- out << details.xact->end_line;
- break;
-
- case element_t::DATE_STRING: {
- datetime_t date;
- if (details.xact)
- date = details.xact->date();
- else if (details.entry)
- date = details.entry->date();
-
- char buf[256];
- std::strftime(buf, 255, elem->chars.c_str(), date.localtime());
- out << (elem->max_width == 0 ? buf : truncate(buf, elem->max_width));
- break;
- }
-
- case element_t::COMPLETE_DATE_STRING: {
- datetime_t actual_date;
- datetime_t effective_date;
- if (details.xact) {
- actual_date = details.xact->actual_date();
- effective_date = details.xact->effective_date();
- }
- else if (details.entry) {
- actual_date = details.entry->actual_date();
- effective_date = details.entry->effective_date();
- }
-
- char abuf[256];
- std::strftime(abuf, 255, elem->chars.c_str(), actual_date.localtime());
-
- if (effective_date && effective_date != actual_date) {
- char buf[512];
- char ebuf[256];
- std::strftime(ebuf, 255, elem->chars.c_str(),
- effective_date.localtime());
-
- std::strcpy(buf, abuf);
- std::strcat(buf, "=");
- std::strcat(buf, ebuf);
-
- out << (elem->max_width == 0 ? buf : truncate(buf, elem->max_width));
- } else {
- out << (elem->max_width == 0 ? abuf : truncate(abuf, elem->max_width));
- }
- break;
- }
-
- case element_t::CLEARED:
- if (details.xact) {
- switch (details.xact->state) {
- case transaction_t::CLEARED:
- out << "* ";
- break;
- case transaction_t::PENDING:
- out << "! ";
- break;
- }
- }
- break;
-
- case element_t::ENTRY_CLEARED:
- if (details.entry) {
- transaction_t::state_t state;
- if (details.entry->get_state(&state))
- switch (state) {
- case transaction_t::CLEARED:
- out << "* ";
- break;
- case transaction_t::PENDING:
- out << "! ";
- break;
- }
- }
- break;
-
- case element_t::CODE: {
- std::string temp;
- if (details.entry && ! details.entry->code.empty()) {
- temp += "(";
- temp += details.entry->code;
- temp += ") ";
- }
- out << temp;
- break;
- }
-
- case element_t::PAYEE:
- if (details.entry)
- out << (elem->max_width == 0 ?
- details.entry->payee : truncate(details.entry->payee,
- elem->max_width));
- break;
-
- case element_t::OPT_NOTE:
- if (details.xact && ! details.xact->note.empty())
- out << " ; ";
- // fall through...
-
- case element_t::NOTE:
- if (details.xact)
- out << (elem->max_width == 0 ?
- details.xact->note : truncate(details.xact->note,
- elem->max_width));
- break;
-
- case element_t::OPT_ACCOUNT:
- if (details.entry && details.xact) {
- transaction_t::state_t state;
- if (! details.entry->get_state(&state))
- switch (details.xact->state) {
- case transaction_t::CLEARED:
- name = "* ";
- break;
- case transaction_t::PENDING:
- name = "! ";
- break;
- }
- }
- // fall through...
-
- case element_t::ACCOUNT_NAME:
- case element_t::ACCOUNT_FULLNAME:
- if (details.account) {
- name += (elem->type == element_t::ACCOUNT_FULLNAME ?
- details.account->fullname() :
- partial_account_name(*details.account));
-
- if (details.xact && details.xact->flags & TRANSACTION_VIRTUAL) {
- if (elem->max_width > 2)
- name = truncate(name, elem->max_width - 2, true);
-
- if (details.xact->flags & TRANSACTION_BALANCE)
- name = "[" + name + "]";
- else
- name = "(" + name + ")";
- }
- else if (elem->max_width > 0)
- name = truncate(name, elem->max_width, true);
-
- out << name;
- } else {
- out << " ";
- }
- break;
-
- case element_t::SPACER:
- out << " ";
- break;
-
- case element_t::DEPTH_SPACER:
- for (const account_t * acct = details.account;
- acct;
- acct = acct->parent)
- if (account_has_xdata(*acct) &&
- account_xdata_(*acct).dflags & ACCOUNT_DISPLAYED) {
- if (elem->min_width > 0 || elem->max_width > 0)
- out.width(elem->min_width > elem->max_width ?
- elem->min_width : elem->max_width);
- out << " ";
- }
- break;
-
- default:
- assert(0);
- break;
- }
-
- std::string temp = out.str();
- if (! ignore_max_width &&
- elem->max_width > 0 && elem->max_width < temp.length())
- temp.erase(elem->max_width);
- out_str << temp;
- }
-}
-
-format_transactions::format_transactions(std::ostream& _output_stream,
- const std::string& format)
- : output_stream(_output_stream), last_entry(NULL), last_xact(NULL)
-{
- const char * f = format.c_str();
- if (const char * p = std::strstr(f, "%/")) {
- first_line_format.reset(std::string(f, 0, p - f));
- next_lines_format.reset(std::string(p + 2));
- } else {
- first_line_format.reset(format);
- next_lines_format.reset(format);
- }
-}
-
-void format_transactions::operator()(transaction_t& xact)
-{
- if (! transaction_has_xdata(xact) ||
- ! (transaction_xdata_(xact).dflags & TRANSACTION_DISPLAYED)) {
- if (last_entry != xact.entry) {
- first_line_format.format(output_stream, details_t(xact));
- last_entry = xact.entry;
- }
- else if (last_xact && last_xact->date() != xact.date()) {
- first_line_format.format(output_stream, details_t(xact));
- }
- else {
- next_lines_format.format(output_stream, details_t(xact));
- }
-
- transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED;
- last_xact = &xact;
- }
-}
-
-void format_entries::format_last_entry()
-{
- bool first = true;
- for (transactions_list::const_iterator i = last_entry->transactions.begin();
- i != last_entry->transactions.end();
- i++) {
- if (transaction_has_xdata(**i) &&
- transaction_xdata_(**i).dflags & TRANSACTION_TO_DISPLAY) {
- if (first) {
- first_line_format.format(output_stream, details_t(**i));
- first = false;
- } else {
- next_lines_format.format(output_stream, details_t(**i));
- }
- transaction_xdata_(**i).dflags |= TRANSACTION_DISPLAYED;
- }
- }
-}
-
-void format_entries::operator()(transaction_t& xact)
-{
- transaction_xdata(xact).dflags |= TRANSACTION_TO_DISPLAY;
-
- if (last_entry && xact.entry != last_entry)
- format_last_entry();
-
- last_entry = xact.entry;
-}
-
-void print_entry(std::ostream& out, const entry_base_t& entry_base,
- const std::string& prefix)
-{
- std::string print_format;
-
- if (const entry_t * entry = dynamic_cast<const entry_t *>(&entry_base)) {
- print_format = (prefix + "%D %X%C%P\n" +
- prefix + " %-34A %12o\n%/" +
- prefix + " %-34A %12o\n");
- }
- else if (const auto_entry_t * entry =
- dynamic_cast<const auto_entry_t *>(&entry_base)) {
- out << "= " << entry->predicate_string << '\n';
- print_format = prefix + " %-34A %12o\n";
- }
- else if (const period_entry_t * entry =
- dynamic_cast<const period_entry_t *>(&entry_base)) {
- out << "~ " << entry->period_string << '\n';
- print_format = prefix + " %-34A %12o\n";
- }
- else {
- assert(0);
- }
-
- format_entries formatter(out, print_format);
- walk_transactions(const_cast<transactions_list&>(entry_base.transactions),
- formatter);
- formatter.flush();
-
- clear_transaction_xdata cleaner;
- walk_transactions(const_cast<transactions_list&>(entry_base.transactions),
- cleaner);
-}
-
-bool disp_subaccounts_p(const account_t& account,
- const item_predicate<account_t>& disp_pred,
- const account_t *& to_show)
-{
- bool display = false;
- unsigned int counted = 0;
- bool matches = disp_pred(account);
- value_t acct_total;
- bool computed = false;
- value_t result;
-
- to_show = NULL;
-
- for (accounts_map::const_iterator i = account.accounts.begin();
- i != account.accounts.end();
- i++) {
- if (! disp_pred(*(*i).second))
- continue;
-
- compute_total(result, details_t(*(*i).second));
- if (! computed) {
- compute_total(acct_total, details_t(account));
- computed = true;
- }
-
- if ((result != acct_total) || counted > 0) {
- display = matches;
- break;
- }
- to_show = (*i).second;
- counted++;
- }
-
- return display;
-}
-
-bool display_account(const account_t& account,
- const item_predicate<account_t>& disp_pred)
-{
- // Never display an account that has already been displayed.
- if (account_has_xdata(account) &&
- account_xdata_(account).dflags & ACCOUNT_DISPLAYED)
- return false;
-
- // At this point, one of two possibilities exists: the account is a
- // leaf which matches the predicate restrictions; or it is a parent
- // and two or more children must be subtotaled; or it is a parent
- // and its child has been hidden by the predicate. So first,
- // determine if it is a parent that must be displayed regardless of
- // the predicate.
-
- const account_t * account_to_show = NULL;
- if (disp_subaccounts_p(account, disp_pred, account_to_show))
- return true;
-
- return ! account_to_show && disp_pred(account);
-}
-
-void format_account::operator()(account_t& account)
-{
- if (display_account(account, disp_pred)) {
- if (! account.parent) {
- account_xdata(account).dflags |= ACCOUNT_TO_DISPLAY;
- } else {
- format.format(output_stream, details_t(account));
- account_xdata(account).dflags |= ACCOUNT_DISPLAYED;
- }
- }
-}
-
-format_equity::format_equity(std::ostream& _output_stream,
- const std::string& _format,
- const std::string& display_predicate)
- : output_stream(_output_stream), disp_pred(display_predicate)
-{
- const char * f = _format.c_str();
- if (const char * p = std::strstr(f, "%/")) {
- first_line_format.reset(std::string(f, 0, p - f));
- next_lines_format.reset(std::string(p + 2));
- } else {
- first_line_format.reset(_format);
- next_lines_format.reset(_format);
- }
-
- entry_t header_entry;
- header_entry.payee = "Opening Balances";
- header_entry._date = datetime_t::now;
- first_line_format.format(output_stream, details_t(header_entry));
-}
-
-void format_equity::flush()
-{
- account_xdata_t xdata;
- xdata.value = total;
- xdata.value.negate();
- account_t summary(NULL, "Equity:Opening Balances");
- summary.data = &xdata;
-
- if (total.type >= value_t::BALANCE) {
- balance_t * bal;
- if (total.type == value_t::BALANCE)
- bal = (balance_t *) total.data;
- else if (total.type == value_t::BALANCE_PAIR)
- bal = &((balance_pair_t *) total.data)->quantity;
- else
- assert(0);
-
- for (amounts_map::const_iterator i = bal->amounts.begin();
- i != bal->amounts.end();
- i++) {
- xdata.value = (*i).second;
- xdata.value.negate();
- next_lines_format.format(output_stream, details_t(summary));
- }
- } else {
- next_lines_format.format(output_stream, details_t(summary));
- }
- output_stream.flush();
-}
-
-void format_equity::operator()(account_t& account)
-{
- if (display_account(account, disp_pred)) {
- if (account_has_xdata(account)) {
- value_t val = account_xdata_(account).value;
-
- if (val.type >= value_t::BALANCE) {
- balance_t * bal;
- if (val.type == value_t::BALANCE)
- bal = (balance_t *) val.data;
- else if (val.type == value_t::BALANCE_PAIR)
- bal = &((balance_pair_t *) val.data)->quantity;
- else
- assert(0);
-
- for (amounts_map::const_iterator i = bal->amounts.begin();
- i != bal->amounts.end();
- i++) {
- account_xdata_(account).value = (*i).second;
- next_lines_format.format(output_stream, details_t(account));
- }
- account_xdata_(account).value = val;
- } else {
- next_lines_format.format(output_stream, details_t(account));
- }
- total += val;
- }
- account_xdata(account).dflags |= ACCOUNT_DISPLAYED;
- }
-}
-
-} // namespace ledger
diff --git a/format.h b/format.h
deleted file mode 100644
index 778ec53f..00000000
--- a/format.h
+++ /dev/null
@@ -1,218 +0,0 @@
-#ifndef _FORMAT_H
-#define _FORMAT_H
-
-#include "journal.h"
-#include "valexpr.h"
-#include "walk.h"
-
-namespace ledger {
-
-std::string truncated(const std::string& str, unsigned int width,
- const int style = 2);
-
-std::string partial_account_name(const account_t& account,
- const unsigned int start_depth);
-
-#define ELEMENT_ALIGN_LEFT 0x01
-#define ELEMENT_HIGHLIGHT 0x02
-
-struct element_t
-{
- enum kind_t {
- STRING,
- VALUE_EXPR,
- SOURCE,
- ENTRY_BEG_POS,
- ENTRY_BEG_LINE,
- ENTRY_END_POS,
- ENTRY_END_LINE,
- XACT_BEG_POS,
- XACT_BEG_LINE,
- XACT_END_POS,
- XACT_END_LINE,
- DATE_STRING,
- COMPLETE_DATE_STRING,
- CLEARED,
- ENTRY_CLEARED,
- CODE,
- PAYEE,
- OPT_ACCOUNT,
- ACCOUNT_NAME,
- ACCOUNT_FULLNAME,
- AMOUNT,
- OPT_AMOUNT,
- TOTAL,
- NOTE,
- OPT_NOTE,
- SPACER,
- DEPTH_SPACER
- };
-
- kind_t type;
- unsigned char flags;
- std::string chars;
- unsigned char min_width;
- unsigned char max_width;
- value_expr val_expr;
-
- struct element_t * next;
-
- element_t() : type(STRING), flags(false),
- min_width(0), max_width(0), next(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor element_t");
- }
-
- ~element_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor element_t");
- if (next) delete next; // recursive, but not too deep
- }
-};
-
-struct format_t
-{
- std::string format_string;
- element_t * elements;
-
- enum elision_style_t {
- TRUNCATE_TRAILING,
- TRUNCATE_MIDDLE,
- TRUNCATE_LEADING,
- ABBREVIATE
- };
-
- static elision_style_t elision_style;
- static int abbrev_length;
-
- static bool ansi_codes;
- static bool ansi_invert;
-
- format_t() : elements(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor format_t");
- }
- format_t(const std::string& _format) : elements(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor format_t");
- reset(_format);
- }
- ~format_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor format_t");
- if (elements) delete elements;
- }
-
- void reset(const std::string& _format) {
- if (elements)
- delete elements;
- elements = parse_elements(_format);
- format_string = _format;
- }
-
- static element_t * parse_elements(const std::string& fmt);
-
- static std::string truncate(const std::string& str, unsigned int width,
- const bool is_account = false);
-
- void format(std::ostream& out, const details_t& details) const;
-};
-
-class format_transactions : public item_handler<transaction_t>
-{
- protected:
- std::ostream& output_stream;
- format_t first_line_format;
- format_t next_lines_format;
- entry_t * last_entry;
- transaction_t * last_xact;
-
- public:
- format_transactions(std::ostream& _output_stream,
- const std::string& format);
-
- virtual void flush() {
- output_stream.flush();
- }
- virtual void operator()(transaction_t& xact);
-};
-
-class format_entries : public format_transactions
-{
- public:
- format_entries(std::ostream& output_stream, const std::string& format)
- : format_transactions(output_stream, format) {}
-
- virtual void format_last_entry();
-
- virtual void flush() {
- if (last_entry) {
- format_last_entry();
- last_entry = NULL;
- }
- format_transactions::flush();
- }
- virtual void operator()(transaction_t& xact);
-};
-
-void print_entry(std::ostream& out, const entry_base_t& entry,
- const std::string& prefix = "");
-
-bool disp_subaccounts_p(const account_t& account,
- const item_predicate<account_t>& disp_pred,
- const account_t *& to_show);
-
-inline bool disp_subaccounts_p(const account_t& account) {
- const account_t * temp;
- return disp_subaccounts_p(account, item_predicate<account_t>(NULL), temp);
-}
-
-bool display_account(const account_t& account,
- const item_predicate<account_t>& disp_pred);
-
-class format_account : public item_handler<account_t>
-{
- std::ostream& output_stream;
-
- item_predicate<account_t> disp_pred;
-
- public:
- format_t format;
-
- format_account(std::ostream& _output_stream,
- const std::string& _format,
- const std::string& display_predicate = NULL)
- : output_stream(_output_stream), disp_pred(display_predicate),
- format(_format) {}
-
- virtual void flush() {
- output_stream.flush();
- }
-
- virtual void operator()(account_t& account);
-};
-
-class format_equity : public item_handler<account_t>
-{
- std::ostream& output_stream;
- format_t first_line_format;
- format_t next_lines_format;
-
- item_predicate<account_t> disp_pred;
-
- mutable value_t total;
-
- public:
- format_equity(std::ostream& _output_stream,
- const std::string& _format,
- const std::string& display_predicate);
-
- virtual void flush();
- virtual void operator()(account_t& account);
-};
-
-class format_error : public error {
- public:
- format_error(const std::string& reason, error_context * ctxt = NULL) throw()
- : error(reason, ctxt) {}
- virtual ~format_error() throw() {}
-};
-
-} // namespace ledger
-
-#endif // _FORMAT_H
diff --git a/gnucash.cc b/gnucash.cc
deleted file mode 100644
index 7d31526d..00000000
--- a/gnucash.cc
+++ /dev/null
@@ -1,413 +0,0 @@
-#include "gnucash.h"
-#include "journal.h"
-#include "format.h"
-#include "error.h"
-#include "acconf.h"
-
-#include <iostream>
-#include <sstream>
-#include <cstring>
-
-extern "C" {
-#if defined(HAVE_EXPAT)
-#include <expat.h> // expat XML parser
-#elif defined(HAVE_XMLPARSE)
-#include <xmlparse.h> // expat XML parser
-#else
-#error "No XML parser library defined."
-#endif
-}
-
-namespace ledger {
-
-typedef std::map<const std::string, account_t *> accounts_map;
-typedef std::pair<const std::string, account_t *> accounts_pair;
-
-typedef std::map<account_t *, commodity_t *> account_comm_map;
-typedef std::pair<account_t *, commodity_t *> account_comm_pair;
-
-static journal_t * curr_journal;
-static account_t * master_account;
-static account_t * curr_account;
-static std::string curr_account_id;
-static entry_t * curr_entry;
-static commodity_t * entry_comm;
-static commodity_t * curr_comm;
-static amount_t curr_value;
-static amount_t curr_quant;
-static XML_Parser current_parser;
-static accounts_map accounts_by_id;
-static account_comm_map account_comms;
-static unsigned int count;
-static std::string have_error;
-
-static std::istream * instreamp;
-static unsigned int offset;
-static XML_Parser parser;
-static std::string path;
-static unsigned int src_idx;
-static istream_pos_type beg_pos;
-static unsigned long beg_line;
-
-static transaction_t::state_t curr_state;
-
-static enum action_t {
- NO_ACTION,
- ACCOUNT_NAME,
- ACCOUNT_ID,
- ACCOUNT_PARENT,
- COMM_SYM,
- COMM_NAME,
- COMM_PREC,
- ENTRY_NUM,
- ALMOST_ENTRY_DATE,
- ENTRY_DATE,
- ENTRY_DESC,
- XACT_STATE,
- XACT_AMOUNT,
- XACT_VALUE,
- XACT_QUANTITY,
- XACT_ACCOUNT,
- XACT_NOTE
-} action;
-
-static void startElement(void *userData, const char *name, const char **atts)
-{
- if (std::strcmp(name, "gnc:account") == 0) {
- curr_account = new account_t(master_account);
- }
- else if (std::strcmp(name, "act:name") == 0)
- action = ACCOUNT_NAME;
- else if (std::strcmp(name, "act:id") == 0)
- action = ACCOUNT_ID;
- else if (std::strcmp(name, "act:parent") == 0)
- action = ACCOUNT_PARENT;
- else if (std::strcmp(name, "gnc:commodity") == 0)
- curr_comm = NULL;
- else if (std::strcmp(name, "cmdty:id") == 0)
- action = COMM_SYM;
- else if (std::strcmp(name, "cmdty:name") == 0)
- action = COMM_NAME;
- else if (std::strcmp(name, "cmdty:fraction") == 0)
- action = COMM_PREC;
- else if (std::strcmp(name, "gnc:transaction") == 0) {
- assert(! curr_entry);
- curr_entry = new entry_t;
- }
- else if (std::strcmp(name, "trn:num") == 0)
- action = ENTRY_NUM;
- else if (std::strcmp(name, "trn:date-posted") == 0)
- action = ALMOST_ENTRY_DATE;
- else if (action == ALMOST_ENTRY_DATE && std::strcmp(name, "ts:date") == 0)
- action = ENTRY_DATE;
- else if (std::strcmp(name, "trn:description") == 0)
- action = ENTRY_DESC;
- else if (std::strcmp(name, "trn:split") == 0) {
- assert(curr_entry);
- curr_entry->add_transaction(new transaction_t(curr_account));
- }
- else if (std::strcmp(name, "split:reconciled-state") == 0)
- action = XACT_STATE;
- else if (std::strcmp(name, "split:amount") == 0)
- action = XACT_AMOUNT;
- else if (std::strcmp(name, "split:value") == 0)
- action = XACT_VALUE;
- else if (std::strcmp(name, "split:quantity") == 0)
- action = XACT_QUANTITY;
- else if (std::strcmp(name, "split:account") == 0)
- action = XACT_ACCOUNT;
- else if (std::strcmp(name, "split:memo") == 0)
- action = XACT_NOTE;
-}
-
-static void endElement(void *userData, const char *name)
-{
- if (std::strcmp(name, "gnc:account") == 0) {
- assert(curr_account);
- if (curr_account->parent == master_account)
- curr_journal->add_account(curr_account);
- accounts_by_id.insert(accounts_pair(curr_account_id, curr_account));
- curr_account = NULL;
- }
- else if (std::strcmp(name, "gnc:commodity") == 0) {
- curr_comm = NULL;
- }
- else if (std::strcmp(name, "gnc:transaction") == 0) {
- assert(curr_entry);
-
- // Add the new entry (what gnucash calls a 'transaction') to the
- // journal
- if (! curr_journal->add_entry(curr_entry)) {
- print_entry(std::cerr, *curr_entry);
- have_error = "The above entry does not balance";
- delete curr_entry;
- } else {
- curr_entry->src_idx = src_idx;
- curr_entry->beg_pos = beg_pos;
- curr_entry->beg_line = beg_line;
- curr_entry->end_pos = instreamp->tellg();
- curr_entry->end_line = XML_GetCurrentLineNumber(parser) - offset;
- count++;
- }
-
- // Clear the relevant variables for the next run
- curr_entry = NULL;
- entry_comm = NULL;
- }
- else if (std::strcmp(name, "trn:split") == 0) {
- transaction_t * xact = curr_entry->transactions.back();
-
- // Identify the commodity to use for the value of this
- // transaction. The quantity indicates how many times that value
- // the transaction is worth.
- amount_t value;
- commodity_t * default_commodity = NULL;
- account_comm_map::iterator ac = account_comms.find(xact->account);
- if (ac != account_comms.end())
- default_commodity = (*ac).second;
-
- if (default_commodity) {
- curr_quant.set_commodity(*default_commodity);
- value = curr_quant.round();
-
- if (curr_value.commodity() == *default_commodity)
- curr_value = value;
- } else {
- value = curr_quant;
- }
-
- xact->state = curr_state;
- xact->amount = value;
- if (value != curr_value)
- xact->cost = new amount_t(curr_value);
-
- xact->beg_pos = beg_pos;
- xact->beg_line = beg_line;
- xact->end_pos = instreamp->tellg();
- xact->end_line = XML_GetCurrentLineNumber(parser) - offset;
-
- // Clear the relevant variables for the next run
- curr_state = transaction_t::UNCLEARED;
- curr_value = amount_t();
- curr_quant = amount_t();
- }
-
- action = NO_ACTION;
-}
-
-
-static amount_t convert_number(const std::string& number,
- int * precision = NULL)
-{
- const char * num = number.c_str();
-
- if (char * p = std::strchr(num, '/')) {
- std::string numer_str(num, p - num);
- std::string denom_str(p + 1);
-
- amount_t amt(numer_str);
- amount_t den(denom_str);
-
- if (precision)
- *precision = denom_str.length() - 1;
-
- if (! den) {
- have_error = "Denominator in entry is zero!";
- return amt;
- } else {
- return amt / den;
- }
- } else {
- return amount_t(number);
- }
-}
-
-static void dataHandler(void *userData, const char *s, int len)
-{
- switch (action) {
- case ACCOUNT_NAME:
- curr_account->name = std::string(s, len);
- break;
-
- case ACCOUNT_ID:
- curr_account_id = std::string(s, len);
- break;
-
- case ACCOUNT_PARENT: {
- accounts_map::iterator i = accounts_by_id.find(std::string(s, len));
- assert(i != accounts_by_id.end());
- curr_account->parent = (*i).second;
- curr_account->depth = curr_account->parent->depth + 1;
- (*i).second->add_account(curr_account);
- break;
- }
-
- case COMM_SYM: {
- std::string symbol(s, len);
- if (symbol == "USD") symbol = "$";
-
- curr_comm = commodity_t::find_or_create(symbol);
- assert(curr_comm);
-
- if (symbol != "$")
- curr_comm->add_flags(COMMODITY_STYLE_SEPARATED);
-
- if (curr_account)
- account_comms.insert(account_comm_pair(curr_account, curr_comm));
- else if (curr_entry)
- entry_comm = curr_comm;
- break;
- }
-
- case COMM_NAME:
- curr_comm->set_name(std::string(s, len));
- break;
-
- case COMM_PREC:
- curr_comm->set_precision(len - 1);
- break;
-
- case ENTRY_NUM:
- curr_entry->code = std::string(s, len);
- break;
-
- case ENTRY_DATE:
- curr_entry->_date = std::string(s, len);
- break;
-
- case ENTRY_DESC:
- curr_entry->payee = std::string(s, len);
- break;
-
- case XACT_STATE:
- if (*s == 'y')
- curr_state = transaction_t::CLEARED;
- else if (*s == 'n')
- curr_state = transaction_t::UNCLEARED;
- else
- curr_state = transaction_t::PENDING;
- break;
-
- case XACT_VALUE: {
- int precision;
- assert(entry_comm);
- curr_value = convert_number(std::string(s, len), &precision);
- curr_value.set_commodity(*entry_comm);
-
- if (precision > entry_comm->precision())
- entry_comm->set_precision(precision);
- break;
- }
-
- case XACT_QUANTITY:
- curr_quant = convert_number(std::string(s, len));
- break;
-
- case XACT_ACCOUNT: {
- transaction_t * xact = curr_entry->transactions.back();
-
- accounts_map::iterator i = accounts_by_id.find(std::string(s, len));
- if (i != accounts_by_id.end()) {
- xact->account = (*i).second;
- } else {
- xact->account = curr_journal->find_account("<Unknown>");
-
- have_error = (std::string("Could not find account ") +
- std::string(s, len));
- }
- break;
- }
-
- case XACT_NOTE:
- curr_entry->transactions.back()->note = std::string(s, len);
- break;
-
- case NO_ACTION:
- case ALMOST_ENTRY_DATE:
- case XACT_AMOUNT:
- break;
-
- default:
- assert(0);
- break;
- }
-}
-
-bool gnucash_parser_t::test(std::istream& in) const
-{
- char buf[5];
- in.read(buf, 5);
- in.clear();
- in.seekg(0, std::ios::beg);
-
- return std::strncmp(buf, "<?xml", 5) == 0;
-}
-
-unsigned int gnucash_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
-{
- char buf[BUFSIZ];
-
- // This is the date format used by Gnucash, so override whatever the
- // user specified.
- date_t::input_format = "%Y-%m-%d %H:%M:%S %z";
-
- count = 0;
- action = NO_ACTION;
- curr_journal = journal;
- master_account = master ? master : journal->master;
- curr_account = NULL;
- curr_entry = NULL;
- curr_comm = NULL;
- entry_comm = NULL;
- curr_state = transaction_t::UNCLEARED;
-
- instreamp = &in;
- path = original_file ? *original_file : "<gnucash>";
- src_idx = journal->sources.size() - 1;
-
- // GnuCash uses the USD commodity without defining it, which really
- // means $.
- commodity_t * usd = commodity_t::find_or_create("$");
- usd->set_precision(2);
- usd->add_flags(COMMODITY_STYLE_THOUSANDS);
-
- offset = 2;
- parser = current_parser = XML_ParserCreate(NULL);
-
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, dataHandler);
-
- while (in.good() && ! in.eof()) {
- beg_pos = in.tellg();
- beg_line = (XML_GetCurrentLineNumber(parser) - offset) + 1;
-
- in.getline(buf, BUFSIZ - 1);
- std::strcat(buf, "\n");
- if (! XML_Parse(parser, buf, std::strlen(buf), in.eof())) {
- unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
- const char * msg = XML_ErrorString(XML_GetErrorCode(parser));
- XML_ParserFree(parser);
- throw new parse_error(msg);
- }
-
- if (! have_error.empty()) {
- unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
- parse_error err(have_error);
- std::cerr << "Error: " << err.what() << std::endl;
- have_error = "";
- }
- }
-
- XML_ParserFree(parser);
-
- accounts_by_id.clear();
- curr_account_id.clear();
-
- return count;
-}
-
-} // namespace ledger
diff --git a/gnucash.h b/gnucash.h
deleted file mode 100644
index 6945e55f..00000000
--- a/gnucash.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _GNUCASH_H
-#define _GNUCASH_H
-
-#include "parser.h"
-
-namespace ledger {
-
-class gnucash_parser_t : public parser_t
-{
- public:
- virtual bool test(std::istream& in) const;
-
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
-};
-
-} // namespace ledger
-
-#endif // _GNUCASH_H
diff --git a/journal.cc b/journal.cc
deleted file mode 100644
index 8ff276eb..00000000
--- a/journal.cc
+++ /dev/null
@@ -1,655 +0,0 @@
-#include "journal.h"
-#include "datetime.h"
-#include "valexpr.h"
-#include "mask.h"
-#include "format.h"
-#include "acconf.h"
-
-#include <fstream>
-
-namespace ledger {
-
-const std::string version = PACKAGE_VERSION;
-
-bool transaction_t::use_effective_date = false;
-
-transaction_t::~transaction_t()
-{
- DEBUG_PRINT("ledger.memory.dtors", "dtor transaction_t");
- if (cost) delete cost;
-}
-
-datetime_t transaction_t::actual_date() const
-{
- if (! _date && entry)
- return entry->actual_date();
- return _date;
-}
-
-datetime_t transaction_t::effective_date() const
-{
- if (! _date_eff && entry)
- return entry->effective_date();
- return _date_eff;
-}
-
-bool transaction_t::valid() const
-{
- if (! entry) {
- DEBUG_PRINT("ledger.validate", "transaction_t: ! entry");
- return false;
- }
-
- if (state != UNCLEARED && state != CLEARED && state != PENDING) {
- DEBUG_PRINT("ledger.validate", "transaction_t: state is bad");
- return false;
- }
-
- bool found = false;
- for (transactions_list::const_iterator i = entry->transactions.begin();
- i != entry->transactions.end();
- i++)
- if (*i == this) {
- found = true;
- break;
- }
- if (! found) {
- DEBUG_PRINT("ledger.validate", "transaction_t: ! found");
- return false;
- }
-
- if (! account) {
- DEBUG_PRINT("ledger.validate", "transaction_t: ! account");
- return false;
- }
-
- if (! amount.valid()) {
- DEBUG_PRINT("ledger.validate", "transaction_t: ! amount.valid()");
- return false;
- }
-
- if (cost && ! cost->valid()) {
- DEBUG_PRINT("ledger.validate", "transaction_t: cost && ! cost->valid()");
- return false;
- }
-
- if (flags & ~0x003f) {
- DEBUG_PRINT("ledger.validate", "transaction_t: flags are bad");
- return false;
- }
-
- return true;
-}
-
-void entry_base_t::add_transaction(transaction_t * xact)
-{
- transactions.push_back(xact);
-}
-
-bool entry_base_t::remove_transaction(transaction_t * xact)
-{
- transactions.remove(xact);
- return true;
-}
-
-bool entry_base_t::finalize()
-{
- // Scan through and compute the total balance for the entry. This
- // is used for auto-calculating the value of entries with no cost,
- // and the per-unit price of unpriced commodities.
-
- value_t balance;
-
- bool no_amounts = true;
- bool saw_null = false;
- for (transactions_list::const_iterator x = transactions.begin();
- x != transactions.end();
- x++)
- if (! ((*x)->flags & TRANSACTION_VIRTUAL) ||
- ((*x)->flags & TRANSACTION_BALANCE)) {
- amount_t * p = (*x)->cost ? (*x)->cost : &(*x)->amount;
- if (*p) {
- if (no_amounts) {
- balance = *p;
- no_amounts = false;
- } else {
- balance += *p;
- }
-
- if ((*x)->cost && (*x)->amount.commodity().annotated) {
- annotated_commodity_t&
- ann_comm(static_cast<annotated_commodity_t&>
- ((*x)->amount.commodity()));
- if (ann_comm.price)
- balance += ann_comm.price * (*x)->amount - *((*x)->cost);
- }
- } else {
- saw_null = true;
- }
- }
-
- // If it's a null entry, then let the user have their fun
- if (no_amounts)
- return true;
-
- // If there is only one transaction, balance against the basket
- // account if one has been set.
-
- if (journal && journal->basket && transactions.size() == 1) {
- assert(balance.type < value_t::BALANCE);
- transaction_t * nxact = new transaction_t(journal->basket);
- // The amount doesn't need to be set because the code below will
- // balance this transaction against the other.
- add_transaction(nxact);
- nxact->flags |= TRANSACTION_CALCULATED;
- }
-
- // If the first transaction of a two-transaction entry is of a
- // different commodity than the other, and it has no per-unit price,
- // determine its price by dividing the unit count into the value of
- // the balance. This is done for the last eligible commodity.
-
- if (! saw_null && balance && balance.type == value_t::BALANCE &&
- ((balance_t *) balance.data)->amounts.size() == 2) {
- transactions_list::const_iterator x = transactions.begin();
- commodity_t& this_comm = (*x)->amount.commodity();
-
- amounts_map::const_iterator this_bal =
- ((balance_t *) balance.data)->amounts.find(&this_comm);
- amounts_map::const_iterator other_bal =
- ((balance_t *) balance.data)->amounts.begin();
- if (this_bal == other_bal)
- other_bal++;
-
- if (this_bal != ((balance_t *) balance.data)->amounts.end()) {
- amount_t per_unit_cost =
- amount_t((*other_bal).second / (*this_bal).second).unround();
-
- for (; x != transactions.end(); x++) {
- if ((*x)->cost || ((*x)->flags & TRANSACTION_VIRTUAL) ||
- ! (*x)->amount || (*x)->amount.commodity() != this_comm)
- continue;
-
- assert((*x)->amount);
- balance -= (*x)->amount;
-
- entry_t * entry = dynamic_cast<entry_t *>(this);
-
- if ((*x)->amount.commodity() &&
- ! (*x)->amount.commodity().annotated)
- (*x)->amount.annotate_commodity(abs(per_unit_cost));
-
- (*x)->cost = new amount_t(- (per_unit_cost * (*x)->amount));
- balance += *(*x)->cost;
- }
- }
- }
-
- // Walk through each of the transactions, fixing up any that we
- // can, and performing any on-the-fly calculations.
-
- bool empty_allowed = true;
-
- for (transactions_list::const_iterator x = transactions.begin();
- x != transactions.end();
- x++) {
- if (! (*x)->amount.null() ||
- (((*x)->flags & TRANSACTION_VIRTUAL) &&
- ! ((*x)->flags & TRANSACTION_BALANCE)))
- continue;
-
- if (! empty_allowed)
- throw new error("Only one transaction with null amount allowed per entry");
- empty_allowed = false;
-
- // If one transaction gives no value at all, its value will become
- // the inverse of the value of the others. If multiple
- // commodities are involved, multiple transactions will be
- // generated to balance them all.
-
- balance_t * bal = NULL;
- switch (balance.type) {
- case value_t::BALANCE_PAIR:
- bal = &((balance_pair_t *) balance.data)->quantity;
- // fall through...
-
- case value_t::BALANCE:
- if (! bal)
- bal = (balance_t *) balance.data;
-
- if (bal->amounts.size() < 2) {
- balance.cast(value_t::AMOUNT);
- } else {
- bool first = true;
- for (amounts_map::const_iterator i = bal->amounts.begin();
- i != bal->amounts.end();
- i++) {
- amount_t amt = (*i).second;
- amt.negate();
-
- if (first) {
- (*x)->amount = amt;
- first = false;
- } else {
- transaction_t * nxact = new transaction_t((*x)->account);
- add_transaction(nxact);
- nxact->flags |= TRANSACTION_CALCULATED;
- nxact->amount = amt;
- }
-
- balance += amt;
- }
- break;
- }
- // fall through...
-
- case value_t::AMOUNT:
- (*x)->amount = *((amount_t *) balance.data);
- (*x)->amount.negate();
- (*x)->flags |= TRANSACTION_CALCULATED;
-
- balance += (*x)->amount;
- break;
-
- default:
- break;
- }
- }
-
- balance.round();
-
- if (balance) {
- error * err =
- new balance_error("Entry does not balance",
- new entry_context(*this, "While balancing entry:"));
- DEBUG_PRINT("ledger.journal.unbalanced_remainder",
- "balance = " << balance);
- err->context.push_front
- (new value_context(balance, "Unbalanced remainder is:"));
- throw err;
- }
-
- return true;
-}
-
-entry_t::entry_t(const entry_t& e)
- : entry_base_t(e), _date(e._date), _date_eff(e._date_eff),
- code(e.code), payee(e.payee)
-{
- DEBUG_PRINT("ledger.memory.ctors", "ctor entry_t");
-
- for (transactions_list::const_iterator i = transactions.begin();
- i != transactions.end();
- i++)
- (*i)->entry = this;
-}
-
-bool entry_t::get_state(transaction_t::state_t * state) const
-{
- bool first = true;
- bool hetero = false;
-
- for (transactions_list::const_iterator i = transactions.begin();
- i != transactions.end();
- i++) {
- if (first) {
- *state = (*i)->state;
- first = false;
- }
- else if (*state != (*i)->state) {
- hetero = true;
- break;
- }
- }
-
- return ! hetero;
-}
-
-void entry_t::add_transaction(transaction_t * xact)
-{
- xact->entry = this;
- entry_base_t::add_transaction(xact);
-}
-
-bool entry_t::valid() const
-{
- if (! _date || ! journal) {
- DEBUG_PRINT("ledger.validate", "entry_t: ! _date || ! journal");
- return false;
- }
-
- for (transactions_list::const_iterator i = transactions.begin();
- i != transactions.end();
- i++)
- if ((*i)->entry != this || ! (*i)->valid()) {
- DEBUG_PRINT("ledger.validate", "entry_t: transaction not valid");
- return false;
- }
-
- return true;
-}
-
-auto_entry_t::auto_entry_t(const std::string& _predicate)
- : predicate_string(_predicate)
-{
- DEBUG_PRINT("ledger.memory.ctors", "ctor auto_entry_t");
- predicate = new item_predicate<transaction_t>(predicate_string);
-}
-
-auto_entry_t::~auto_entry_t()
-{
- DEBUG_PRINT("ledger.memory.dtors", "dtor auto_entry_t");
- if (predicate)
- delete predicate;
-}
-
-void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
-{
- transactions_list initial_xacts(entry.transactions.begin(),
- entry.transactions.end());
-
- for (transactions_list::iterator i = initial_xacts.begin();
- i != initial_xacts.end();
- i++) {
- if ((*predicate)(**i)) {
- for (transactions_list::iterator t = transactions.begin();
- t != transactions.end();
- t++) {
- amount_t amt;
- if (! (*t)->amount.commodity()) {
- if (! post)
- continue;
- amt = (*i)->amount * (*t)->amount;
- } else {
- if (post)
- continue;
- amt = (*t)->amount;
- }
-
- account_t * account = (*t)->account;
- std::string fullname = account->fullname();
- assert(! fullname.empty());
- if (fullname == "$account" || fullname == "@account")
- account = (*i)->account;
-
- transaction_t * xact
- = new transaction_t(account, amt, (*t)->flags | TRANSACTION_AUTO);
-
- // Copy over details so that the resulting transaction is a mirror of
- // the automated entry's one.
- xact->state = (*t)->state;
- xact->_date = (*t)->_date;
- xact->_date_eff = (*t)->_date_eff;
- xact->note = (*t)->note;
- xact->beg_pos = (*t)->beg_pos;
- xact->beg_line = (*t)->beg_line;
- xact->end_pos = (*t)->end_pos;
- xact->end_line = (*t)->end_line;
-
- entry.add_transaction(xact);
- }
- }
- }
-}
-
-account_t::~account_t()
-{
- DEBUG_PRINT("ledger.memory.dtors", "dtor account_t " << this);
- //assert(! data);
-
- for (accounts_map::iterator i = accounts.begin();
- i != accounts.end();
- i++)
- delete (*i).second;
-}
-
-account_t * account_t::find_account(const std::string& name,
- const bool auto_create)
-{
- accounts_map::const_iterator i = accounts.find(name);
- if (i != accounts.end())
- return (*i).second;
-
- char buf[256];
-
- std::string::size_type sep = name.find(':');
- assert(sep < 256|| sep == std::string::npos);
-
- const char * first, * rest;
- if (sep == std::string::npos) {
- first = name.c_str();
- rest = NULL;
- } else {
- std::strncpy(buf, name.c_str(), sep);
- buf[sep] = '\0';
-
- first = buf;
- rest = name.c_str() + sep + 1;
- }
-
- account_t * account;
-
- i = accounts.find(first);
- if (i == accounts.end()) {
- if (! auto_create)
- return NULL;
-
- account = new account_t(this, first);
- account->journal = journal;
-
- std::pair<accounts_map::iterator, bool> result
- = accounts.insert(accounts_pair(first, account));
- assert(result.second);
- } else {
- account = (*i).second;
- }
-
- if (rest)
- account = account->find_account(rest, auto_create);
-
- return account;
-}
-
-static inline
-account_t * find_account_re_(account_t * account, const mask_t& regexp)
-{
- if (regexp.match(account->fullname()))
- return account;
-
- for (accounts_map::iterator i = account->accounts.begin();
- i != account->accounts.end();
- i++)
- if (account_t * a = find_account_re_((*i).second, regexp))
- return a;
-
- return NULL;
-}
-
-account_t * journal_t::find_account_re(const std::string& regexp)
-{
- return find_account_re_(master, mask_t(regexp));
-}
-
-std::string account_t::fullname() const
-{
- if (! _fullname.empty()) {
- return _fullname;
- } else {
- const account_t * first = this;
- std::string fullname = name;
-
- while (first->parent) {
- first = first->parent;
- if (! first->name.empty())
- fullname = first->name + ":" + fullname;
- }
-
- _fullname = fullname;
-
- return fullname;
- }
-}
-
-std::ostream& operator<<(std::ostream& out, const account_t& account)
-{
- out << account.fullname();
- return out;
-}
-
-bool account_t::valid() const
-{
- if (depth > 256 || ! journal) {
- DEBUG_PRINT("ledger.validate", "account_t: depth > 256 || ! journal");
- return false;
- }
-
- for (accounts_map::const_iterator i = accounts.begin();
- i != accounts.end();
- i++) {
- if (this == (*i).second) {
- DEBUG_PRINT("ledger.validate", "account_t: parent refers to itself!");
- return false;
- }
-
- if (! (*i).second->valid()) {
- DEBUG_PRINT("ledger.validate", "account_t: child not valid");
- return false;
- }
- }
-
- return true;
-}
-
-journal_t::~journal_t()
-{
- DEBUG_PRINT("ledger.memory.dtors", "dtor journal_t");
-
- assert(master);
- delete master;
-
- // Don't bother unhooking each entry's transactions from the
- // accounts they refer to, because all accounts are about to
- // be deleted.
- for (entries_list::iterator i = entries.begin();
- i != entries.end();
- i++)
- if (! item_pool ||
- ((char *) *i) < item_pool || ((char *) *i) >= item_pool_end)
- delete *i;
- else
- (*i)->~entry_t();
-
- for (auto_entries_list::iterator i = auto_entries.begin();
- i != auto_entries.end();
- i++)
- if (! item_pool ||
- ((char *) *i) < item_pool || ((char *) *i) >= item_pool_end)
- delete *i;
- else
- (*i)->~auto_entry_t();
-
- for (period_entries_list::iterator i = period_entries.begin();
- i != period_entries.end();
- i++)
- if (! item_pool ||
- ((char *) *i) < item_pool || ((char *) *i) >= item_pool_end)
- delete *i;
- else
- (*i)->~period_entry_t();
-
- if (item_pool)
- delete[] item_pool;
-}
-
-bool journal_t::add_entry(entry_t * entry)
-{
- entry->journal = this;
-
- if (! run_hooks(entry_finalize_hooks, *entry, false) ||
- ! entry->finalize() ||
- ! run_hooks(entry_finalize_hooks, *entry, true)) {
- entry->journal = NULL;
- return false;
- }
-
- entries.push_back(entry);
-
- for (transactions_list::const_iterator i = entry->transactions.begin();
- i != entry->transactions.end();
- i++)
- if ((*i)->cost && (*i)->amount)
- (*i)->amount.commodity().add_price(entry->date(),
- *(*i)->cost / (*i)->amount);
-
- return true;
-}
-
-bool journal_t::remove_entry(entry_t * entry)
-{
- bool found = false;
- entries_list::iterator i;
- for (i = entries.begin(); i != entries.end(); i++)
- if (*i == entry) {
- found = true;
- break;
- }
- if (! found)
- return false;
-
- entries.erase(i);
- entry->journal = NULL;
-
- return true;
-}
-
-bool journal_t::valid() const
-{
- if (! master->valid()) {
- DEBUG_PRINT("ledger.validate", "journal_t: master not valid");
- return false;
- }
-
- for (entries_list::const_iterator i = entries.begin();
- i != entries.end();
- i++)
- if (! (*i)->valid()) {
- DEBUG_PRINT("ledger.validate", "journal_t: entry not valid");
- return false;
- }
-
- for (commodities_map::const_iterator i = commodity_t::commodities.begin();
- i != commodity_t::commodities.end();
- i++)
- if (! (*i).second->valid()) {
- DEBUG_PRINT("ledger.validate", "journal_t: commodity not valid");
- return false;
- }
-
- return true;
-}
-
-void entry_context::describe(std::ostream& out) const throw()
-{
- if (! desc.empty())
- out << desc << std::endl;
-
- print_entry(out, entry, " ");
-}
-
-xact_context::xact_context(const ledger::transaction_t& _xact,
- const std::string& desc) throw()
- : xact(_xact), file_context("", 0, desc)
-{
- const ledger::strings_list& sources(xact.entry->journal->sources);
- int x = 0;
- for (ledger::strings_list::const_iterator i = sources.begin();
- i != sources.end();
- i++, x++)
- if (x == xact.entry->src_idx) {
- file = *i;
- break;
- }
- line = xact.beg_line;
-}
-
-} // namespace ledger
diff --git a/journal.h b/journal.h
deleted file mode 100644
index 212590cf..00000000
--- a/journal.h
+++ /dev/null
@@ -1,466 +0,0 @@
-#ifndef _JOURNAL_H
-#define _JOURNAL_H
-
-#include <map>
-#include <list>
-#include <string>
-#include <iostream>
-
-#include "amount.h"
-#include "datetime.h"
-#include "value.h"
-#include "valexpr.h"
-#include "error.h"
-#include "debug.h"
-#include "util.h"
-
-namespace ledger {
-
-// These flags persist with the object
-#define TRANSACTION_NORMAL 0x0000
-#define TRANSACTION_VIRTUAL 0x0001
-#define TRANSACTION_BALANCE 0x0002
-#define TRANSACTION_AUTO 0x0004
-#define TRANSACTION_BULK_ALLOC 0x0008
-#define TRANSACTION_CALCULATED 0x0010
-
-class entry_t;
-class account_t;
-
-class transaction_t
-{
- public:
- enum state_t { UNCLEARED, CLEARED, PENDING };
-
- entry_t * entry;
- datetime_t _date;
- datetime_t _date_eff;
- account_t * account;
- amount_t amount;
- value_expr amount_expr;
- amount_t * cost;
- std::string cost_expr;
- state_t state;
- unsigned short flags;
- std::string note;
- istream_pos_type beg_pos;
- unsigned long beg_line;
- istream_pos_type end_pos;
- unsigned long end_line;
- mutable void * data;
-
- static bool use_effective_date;
-
- transaction_t(account_t * _account = NULL)
- : entry(NULL), account(_account), cost(NULL),
- state(UNCLEARED), flags(TRANSACTION_NORMAL),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t");
- }
- transaction_t(account_t * _account,
- const amount_t& _amount,
- unsigned int _flags = TRANSACTION_NORMAL,
- const std::string& _note = "")
- : entry(NULL), account(_account), amount(_amount), cost(NULL),
- state(UNCLEARED), flags(_flags),
- note(_note), beg_pos(0), beg_line(0), end_pos(0), end_line(0),
- data(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t");
- }
- transaction_t(const transaction_t& xact)
- : entry(xact.entry), account(xact.account), amount(xact.amount),
- cost(xact.cost ? new amount_t(*xact.cost) : NULL),
- state(xact.state), flags(xact.flags), note(xact.note),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t");
- }
- ~transaction_t();
-
- datetime_t actual_date() const;
- datetime_t effective_date() const;
- datetime_t date() const {
- if (use_effective_date)
- return effective_date();
- else
- return actual_date();
- }
-
- bool operator==(const transaction_t& xact) {
- return this == &xact;
- }
- bool operator!=(const transaction_t& xact) {
- return ! (*this == xact);
- }
-
- bool valid() const;
-};
-
-class xact_context : public file_context {
- public:
- const transaction_t& xact;
-
- xact_context(const transaction_t& _xact,
- const std::string& desc = "") throw();
- virtual ~xact_context() throw() {}
-};
-
-class journal_t;
-
-typedef std::list<transaction_t *> transactions_list;
-
-class entry_base_t
-{
- public:
- journal_t * journal;
- unsigned long src_idx;
- istream_pos_type beg_pos;
- unsigned long beg_line;
- istream_pos_type end_pos;
- unsigned long end_line;
- transactions_list transactions;
-
- entry_base_t() : journal(NULL),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0)
- {
- DEBUG_PRINT("ledger.memory.ctors", "ctor entry_base_t");
- }
- entry_base_t(const entry_base_t& e) : journal(NULL),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0)
- {
- DEBUG_PRINT("ledger.memory.ctors", "ctor entry_base_t");
- for (transactions_list::const_iterator i = e.transactions.begin();
- i != e.transactions.end();
- i++)
- transactions.push_back(new transaction_t(**i));
- }
- virtual ~entry_base_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor entry_base_t");
- for (transactions_list::iterator i = transactions.begin();
- i != transactions.end();
- i++)
- if (! ((*i)->flags & TRANSACTION_BULK_ALLOC))
- delete *i;
- else
- (*i)->~transaction_t();
- }
-
- bool operator==(const entry_base_t& entry) {
- return this == &entry;
- }
- bool operator!=(const entry_base_t& entry) {
- return ! (*this == entry);
- }
-
- virtual void add_transaction(transaction_t * xact);
- virtual bool remove_transaction(transaction_t * xact);
-
- virtual bool finalize();
- virtual bool valid() const = 0;
-};
-
-class entry_t : public entry_base_t
-{
- public:
- datetime_t _date;
- datetime_t _date_eff;
- std::string code;
- std::string payee;
-
- entry_t() {
- DEBUG_PRINT("ledger.memory.ctors", "ctor entry_t");
- }
- entry_t(const entry_t& e);
-
- virtual ~entry_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor entry_t");
- }
-
- datetime_t actual_date() const {
- return _date;
- }
- datetime_t effective_date() const {
- if (! _date_eff)
- return _date;
- return _date_eff;
- }
- datetime_t date() const {
- if (transaction_t::use_effective_date)
- return effective_date();
- else
- return actual_date();
- }
-
- virtual void add_transaction(transaction_t * xact);
-
- virtual bool valid() const;
-
- bool get_state(transaction_t::state_t * state) const;
-};
-
-struct entry_finalizer_t {
- virtual ~entry_finalizer_t() {}
- virtual bool operator()(entry_t& entry, bool post) = 0;
-};
-
-class entry_context : public error_context {
- public:
- const entry_base_t& entry;
-
- entry_context(const entry_base_t& _entry,
- const std::string& desc = "") throw()
- : error_context(desc), entry(_entry) {}
- virtual ~entry_context() throw() {}
-
- virtual void describe(std::ostream& out) const throw();
-};
-
-class balance_error : public error {
- public:
- balance_error(const std::string& reason, error_context * ctxt = NULL) throw()
- : error(reason, ctxt) {}
- virtual ~balance_error() throw() {}
-};
-
-
-template <typename T>
-class item_predicate;
-
-class auto_entry_t : public entry_base_t
-{
-public:
- item_predicate<transaction_t> * predicate;
- std::string predicate_string;
-
- auto_entry_t() : predicate(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor auto_entry_t");
- }
- auto_entry_t(const std::string& _predicate);
-
- virtual ~auto_entry_t();
-
- virtual void extend_entry(entry_base_t& entry, bool post);
- virtual bool valid() const {
- return true;
- }
-};
-
-class journal_t;
-struct auto_entry_finalizer_t : public entry_finalizer_t {
- journal_t * journal;
- auto_entry_finalizer_t(journal_t * _journal) : journal(_journal) {}
- virtual bool operator()(entry_t& entry, bool post);
-};
-
-
-class period_entry_t : public entry_base_t
-{
- public:
- interval_t period;
- std::string period_string;
-
- period_entry_t() {
- DEBUG_PRINT("ledger.memory.ctors", "ctor period_entry_t");
- }
- period_entry_t(const std::string& _period)
- : period(_period), period_string(_period) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor period_entry_t");
- }
- period_entry_t(const period_entry_t& e)
- : entry_base_t(e), period(e.period), period_string(e.period_string) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor period_entry_t");
- }
-
- virtual ~period_entry_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor period_entry_t");
- }
-
- virtual bool valid() const {
- return period;
- }
-};
-
-
-typedef std::map<const std::string, account_t *> accounts_map;
-typedef std::pair<const std::string, account_t *> accounts_pair;
-
-class account_t
-{
- public:
- typedef unsigned long ident_t;
-
- journal_t * journal;
- account_t * parent;
- std::string name;
- std::string note;
- unsigned short depth;
- accounts_map accounts;
-
- mutable void * data;
- mutable ident_t ident;
- mutable std::string _fullname;
-
- account_t(account_t * _parent = NULL,
- const std::string& _name = "",
- const std::string& _note = "")
- : parent(_parent), name(_name), note(_note),
- depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor account_t " << this);
- }
- ~account_t();
-
- bool operator==(const account_t& account) {
- return this == &account;
- }
- bool operator!=(const account_t& account) {
- return ! (*this == account);
- }
-
- std::string fullname() const;
-
- void add_account(account_t * acct) {
- accounts.insert(accounts_pair(acct->name, acct));
- acct->journal = journal;
- }
- bool remove_account(account_t * acct) {
- accounts_map::size_type n = accounts.erase(acct->name);
- acct->journal = NULL;
- return n > 0;
- }
-
- account_t * find_account(const std::string& name, bool auto_create = true);
-
- operator std::string() const {
- return fullname();
- }
-
- bool valid() const;
-
- friend class journal_t;
-};
-
-std::ostream& operator<<(std::ostream& out, const account_t& account);
-
-
-struct func_finalizer_t : public entry_finalizer_t {
- typedef bool (*func_t)(entry_t& entry, bool post);
- func_t func;
- func_finalizer_t(func_t _func) : func(_func) {}
- func_finalizer_t(const func_finalizer_t& other) : func(other.func) {}
- virtual bool operator()(entry_t& entry, bool post) {
- return func(entry, post);
- }
-};
-
-template <typename T>
-void add_hook(std::list<T>& list, T obj, const bool prepend = false) {
- if (prepend)
- list.push_front(obj);
- else
- list.push_back(obj);
-}
-
-template <typename T>
-void remove_hook(std::list<T>& list, T obj) {
- list.remove(obj);
-}
-
-template <typename T, typename Data>
-bool run_hooks(std::list<T>& list, Data& item, bool post) {
- for (typename std::list<T>::const_iterator i = list.begin();
- i != list.end();
- i++)
- if (! (*(*i))(item, post))
- return false;
- return true;
-}
-
-
-typedef std::list<entry_t *> entries_list;
-typedef std::list<auto_entry_t *> auto_entries_list;
-typedef std::list<period_entry_t *> period_entries_list;
-typedef std::list<std::string> strings_list;
-
-class journal_t
-{
- public:
- account_t * master;
- account_t * basket;
- entries_list entries;
- strings_list sources;
- std::string price_db;
- char * item_pool;
- char * item_pool_end;
-
- auto_entries_list auto_entries;
- period_entries_list period_entries;
- mutable accounts_map accounts_cache;
-
- std::list<entry_finalizer_t *> entry_finalize_hooks;
-
- journal_t() : basket(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor journal_t");
- master = new account_t(NULL, "");
- master->journal = this;
- item_pool = item_pool_end = NULL;
- }
- ~journal_t();
-
- bool operator==(const journal_t& journal) {
- return this == &journal;
- }
- bool operator!=(const journal_t& journal) {
- return ! (*this == journal);
- }
-
- void add_account(account_t * acct) {
- master->add_account(acct);
- acct->journal = this;
- }
- bool remove_account(account_t * acct) {
- return master->remove_account(acct);
- acct->journal = NULL;
- }
-
- account_t * find_account(const std::string& name, bool auto_create = true) {
- accounts_map::iterator c = accounts_cache.find(name);
- if (c != accounts_cache.end())
- return (*c).second;
-
- account_t * account = master->find_account(name, auto_create);
- accounts_cache.insert(accounts_pair(name, account));
- account->journal = this;
- return account;
- }
- account_t * find_account_re(const std::string& regexp);
-
- bool add_entry(entry_t * entry);
- bool remove_entry(entry_t * entry);
-
- void add_entry_finalizer(entry_finalizer_t * finalizer) {
- add_hook<entry_finalizer_t *>(entry_finalize_hooks, finalizer);
- }
- void remove_entry_finalizer(entry_finalizer_t * finalizer) {
- remove_hook<entry_finalizer_t *>(entry_finalize_hooks, finalizer);
- }
-
- bool valid() const;
-};
-
-inline void extend_entry_base(journal_t * journal, entry_base_t& entry,
- bool post) {
- for (auto_entries_list::iterator i = journal->auto_entries.begin();
- i != journal->auto_entries.end();
- i++)
- (*i)->extend_entry(entry, post);
-}
-
-inline bool auto_entry_finalizer_t::operator()(entry_t& entry, bool post) {
- extend_entry_base(journal, entry, post);
- return true;
-}
-
-extern const std::string version;
-
-} // namespace ledger
-
-#endif // _JOURNAL_H
diff --git a/ledger.h b/ledger.h
deleted file mode 100644
index a59d562d..00000000
--- a/ledger.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef _LEDGER_H
-#define _LEDGER_H
-
-//////////////////////////////////////////////////////////////////////
-//
-// Ledger Accounting Tool
-//
-// A command-line tool for general double-entry accounting.
-//
-// Copyright (c) 2003,2004 John Wiegley <johnw@newartisans.com>
-//
-
-#include <amount.h>
-#include <balance.h>
-#include <value.h>
-
-#include <journal.h>
-
-#include <datetime.h>
-#include <format.h>
-#include <emacs.h>
-#include <csv.h>
-#include <quotes.h>
-#include <valexpr.h>
-#include <walk.h>
-#include <derive.h>
-#include <reconcile.h>
-#include <error.h>
-#include <option.h>
-
-#include <parser.h>
-#include <textual.h>
-#include <binary.h>
-#include <xml.h>
-#include <gnucash.h>
-#include <qif.h>
-#include <ofx.h>
-
-namespace ledger {
- extern parser_t * binary_parser_ptr;
- extern parser_t * xml_parser_ptr;
- extern parser_t * gnucash_parser_ptr;
- extern parser_t * ofx_parser_ptr;
- extern parser_t * qif_parser_ptr;
- extern parser_t * textual_parser_ptr;
-}
-
-#include <config.h>
-#include <report.h>
-
-#endif // _LEDGER_H
diff --git a/ledger.vim b/ledger.vim
deleted file mode 100644
index df63feb8..00000000
--- a/ledger.vim
+++ /dev/null
@@ -1,46 +0,0 @@
-" Vim syntax file
-" filetype: ledger
-" Version: 0.0.2
-" by Wolfgang Oertl; Use according to the terms of the GPL>=2.
-" Revision history
-" 2005-02-05 first version (partly copied from ledger.vim 0.0.1)
-
-if version < 600
- syntax clear
-elseif exists("b:current_sytax")
- finish
-endif
-
-" for debugging
-syntax clear
-
-" region: a normal transaction
-syn region transNorm start=/^\d/ skip=/^\s/ end=/^/ fold keepend transparent contains=transDate
-syn match transDate /^\d\S\+/ contained
-syn match Comment /^;.*$/
-" highlight default link transNorm Question
-highlight default link Comment SpecialKey
-highlight default link transDate Question
-
-" folding: how to represent a transaction in one line.
-function! MyFoldText()
- let line = strpart(getline(v:foldstart), 0, 65)
- " get the amount at the end of the second line
- let line2 = getline(v:foldstart+1)
- let pos = match(line2, "[0-9.]*$")
- let line2 = strpart(line2, pos)
- let pad_len = 80 - strlen(line) - strlen(line2)
- if (pad_len < 0) then
- pad_len = 0
- endif
- let pad = strpart(" ", 0, pad_len)
- return line . pad . line2
-endfunction
-set foldtext=MyFoldText()
-set foldmethod=syntax
-
-" syncinc is easy: search for the first transaction.
-syn sync clear
-syn sync match ledgerSync grouphere transNorm "^\d"
-
-let b:current_syntax = "ledger"
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 00000000..7714f21d
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,59 @@
+# Uncomment these if you are on OS X and want to build universal libraries.
+# This is only important if you intend to produce a Ledger binary for
+# installation.
+
+STOW_ROOT = /usr/local/stow
+PRODUCTS = $(HOME)/Products
+
+CC = gcc-mp-4.4
+CXX = g++-mp-4.4
+LD = gcc-mp-4.4
+CPPFLAGS = -D_GLIBCXX_DEBUG=1 -D_GLIBCXX_FULLY_DYNAMIC_STRING=1
+CFLAGS = $(CPPFLAGS) -g
+LDFLAGS = -g
+
+BOOST_VERSION = 1_41_0
+BOOST_SOURCE = boost_$(BOOST_VERSION)
+BOOST_TOOLSET = darwin
+BOOST_DEFINES = define=_GLIBCXX_DEBUG=1 define=_GLIBCXX_FULLY_DYNAMIC_STRING=1
+#BOOST_FLAGS = --architecture=x86 --address_model=32_64
+BOOST_FLAGS = --toolset=$(BOOST_TOOLSET) \
+ --build-type=complete --layout=versioned \
+ $(BOOST_DEFINES)
+ICU_FLAGS = -sHAVE_ICU=1 -sICU_PATH=$(STOW_ROOT)/icu
+
+all: boost-build cppunit-build icu-build boost-icu-build
+
+boost-build:
+ (cd $(BOOST_SOURCE) && \
+ bjam debug --prefix=$(STOW_ROOT)/boost_$(BOOST_VERSION) \
+ --build-dir=$(PRODUCTS)/boost_$(BOOST_VERSION) \
+ $(BOOST_FLAGS) install)
+
+cppunit-build:
+ -(cd cppunit; make distclean)
+ (cd cppunit; sh autogen.sh; \
+ ./configure CPPFLAGS="$(CPPFLAGS)" \
+ CFLAGS="$(CFLAGS)" \
+ LDFLAGS="$(LDFLAGS)" \
+ CC="$(CC)" CXX="$(CXX)" LD="$(LD)" \
+ --prefix=$(STOW_ROOT)/cppunit \
+ --disable-doxygen --disable-dot && \
+ make install)
+
+icu-build:
+ -(cd icu/source; make distclean)
+ (cd icu/source; sh autogen.sh; \
+ ./configure CPPFLAGS="$(CPPFLAGS)" \
+ CFLAGS="$(CFLAGS)" \
+ LDFLAGS="$(LDFLAGS)" \
+ CC="$(CC)" CXX="$(CXX)" LD="$(LD)" \
+ --enable-static --enable-debug \
+ --prefix=$(STOW_ROOT)/icu && \
+ make install)
+
+boost-icu-build:
+ (cd $(BOOST_SOURCE) && \
+ bjam debug --prefix=$(STOW_ROOT)/boost_$(BOOST_VERSION)-icu \
+ --build-dir=$(PRODUCTS)/boost_$(BOOST_VERSION)-icu \
+ $(BOOST_FLAGS) $(ICU_FLAGS) install)
diff --git a/lib/gettext.h b/lib/gettext.h
new file mode 100644
index 00000000..209921e6
--- /dev/null
+++ b/lib/gettext.h
@@ -0,0 +1,271 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+ Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option. */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions. */
+# include <libintl.h>
+
+/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
+ the gettext() and ngettext() macros. This is an alternative to calling
+ textdomain(), and is useful for libraries. */
+# ifdef DEFAULT_TEXT_DOMAIN
+# undef gettext
+# define gettext(Msgid) \
+ dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
+# undef ngettext
+# define ngettext(Msgid1, Msgid2, N) \
+ dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
+# endif
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+ chokes if dcgettext is defined as a macro. So include it now, to make
+ later inclusions of <locale.h> a NOP. We don't include <libintl.h>
+ as well because people using "gettext.h" will not include <libintl.h>,
+ and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+ is OK. */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
+ <libintl.h>, which chokes if dcgettext is defined as a macro. So include
+ it now, to make later inclusions of <libintl.h> a NOP. */
+#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
+# include <cstdlib>
+# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
+# include <libintl.h>
+# endif
+#endif
+
+/* Disabled NLS.
+ The casts to 'const char *' serve the purpose of producing warnings
+ for invalid uses of the value returned from these functions.
+ On pre-ANSI systems without 'const', the config.h file is supposed to
+ contain "#define const". */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
+# define dcgettext(Domainname, Msgid, Category) \
+ ((void) (Category), dgettext (Domainname, Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+ ((N) == 1 \
+ ? ((void) (Msgid2), (const char *) (Msgid1)) \
+ : ((void) (Msgid1), (const char *) (Msgid2)))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+ ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+ ((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) \
+ ((void) (Domainname), (const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) \
+ ((void) (Domainname), (const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+ extraction of messages, but does not call gettext(). The run-time
+ translation is done at a different place in the code.
+ The argument, String, should be a literal string. Concatenated strings
+ and other string expressions won't work.
+ The macro's expansion is not parenthesized, so that it is suitable as
+ initializer for static 'char[]' or 'const char[]' variables. */
+#define gettext_noop(String) String
+
+/* The separator between msgctxt and msgid in a .mo file. */
+#define GETTEXT_CONTEXT_GLUE "\004"
+
+/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
+ MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
+ short and rarely need to change.
+ The letter 'p' stands for 'particular' or 'special'. */
+#ifdef DEFAULT_TEXT_DOMAIN
+# define pgettext(Msgctxt, Msgid) \
+ pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#else
+# define pgettext(Msgctxt, Msgid) \
+ pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#endif
+#define dpgettext(Domainname, Msgctxt, Msgid) \
+ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
+ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
+#ifdef DEFAULT_TEXT_DOMAIN
+# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#else
+# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#endif
+#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
+ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+pgettext_aux (const char *domain,
+ const char *msg_ctxt_id, const char *msgid,
+ int category)
+{
+ const char *translation = dcgettext (domain, msg_ctxt_id, category);
+ if (translation == msg_ctxt_id)
+ return msgid;
+ else
+ return translation;
+}
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+npgettext_aux (const char *domain,
+ const char *msg_ctxt_id, const char *msgid,
+ const char *msgid_plural, unsigned long int n,
+ int category)
+{
+ const char *translation =
+ dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
+ if (translation == msg_ctxt_id || translation == msgid_plural)
+ return (n == 1 ? msgid : msgid_plural);
+ else
+ return translation;
+}
+
+/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
+ can be arbitrary expressions. But for string literals these macros are
+ less efficient than those above. */
+
+#include <string.h>
+
+#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
+ (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
+ /* || __STDC_VERSION__ >= 199901L */ )
+
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+#include <stdlib.h>
+#endif
+
+#define pgettext_expr(Msgctxt, Msgid) \
+ dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
+#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
+ dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+dcpgettext_expr (const char *domain,
+ const char *msgctxt, const char *msgid,
+ int category)
+{
+ size_t msgctxt_len = strlen (msgctxt) + 1;
+ size_t msgid_len = strlen (msgid) + 1;
+ const char *translation;
+#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ char msg_ctxt_id[msgctxt_len + msgid_len];
+#else
+ char buf[1024];
+ char *msg_ctxt_id =
+ (msgctxt_len + msgid_len <= sizeof (buf)
+ ? buf
+ : (char *) malloc (msgctxt_len + msgid_len));
+ if (msg_ctxt_id != NULL)
+#endif
+ {
+ memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
+ msg_ctxt_id[msgctxt_len - 1] = '\004';
+ memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
+ translation = dcgettext (domain, msg_ctxt_id, category);
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ if (msg_ctxt_id != buf)
+ free (msg_ctxt_id);
+#endif
+ if (translation != msg_ctxt_id)
+ return translation;
+ }
+ return msgid;
+}
+
+#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
+ dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
+#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
+ dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+dcnpgettext_expr (const char *domain,
+ const char *msgctxt, const char *msgid,
+ const char *msgid_plural, unsigned long int n,
+ int category)
+{
+ size_t msgctxt_len = strlen (msgctxt) + 1;
+ size_t msgid_len = strlen (msgid) + 1;
+ const char *translation;
+#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ char msg_ctxt_id[msgctxt_len + msgid_len];
+#else
+ char buf[1024];
+ char *msg_ctxt_id =
+ (msgctxt_len + msgid_len <= sizeof (buf)
+ ? buf
+ : (char *) malloc (msgctxt_len + msgid_len));
+ if (msg_ctxt_id != NULL)
+#endif
+ {
+ memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
+ msg_ctxt_id[msgctxt_len - 1] = '\004';
+ memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
+ translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ if (msg_ctxt_id != buf)
+ free (msg_ctxt_id);
+#endif
+ if (!(translation == msg_ctxt_id || translation == msgid_plural))
+ return translation;
+ }
+ return (n == 1 ? msgid : msgid_plural);
+}
+
+#endif /* _LIBGETTEXT_H */
diff --git a/lib/sha1.cpp b/lib/sha1.cpp
new file mode 100644
index 00000000..8689d711
--- /dev/null
+++ b/lib/sha1.cpp
@@ -0,0 +1,589 @@
+/*
+ * sha1.cpp
+ *
+ * Copyright (C) 1998
+ * Paul E. Jones <paulej@arid.us>
+ * All Rights Reserved.
+ *
+ *****************************************************************************
+ * $Id: sha1.cpp,v 1.9 2004/03/27 18:02:20 paulej Exp $
+ *****************************************************************************
+ *
+ * Description:
+ * This class implements the Secure Hashing Standard as defined
+ * in FIPS PUB 180-1 published April 17, 1995.
+ *
+ * The Secure Hashing Standard, which uses the Secure Hashing
+ * Algorithm (SHA), produces a 160-bit message digest for a
+ * given data stream. In theory, it is highly improbable that
+ * two messages will produce the same message digest. Therefore,
+ * this algorithm can serve as a means of providing a "fingerprint"
+ * for a message.
+ *
+ * Portability Issues:
+ * SHA-1 is defined in terms of 32-bit "words". This code was
+ * written with the expectation that the processor has at least
+ * a 32-bit machine word size. If the machine word size is larger,
+ * the code should still function properly. One caveat to that
+ * is that the input functions taking characters and character arrays
+ * assume that only 8 bits of information are stored in each character.
+ *
+ * Caveats:
+ * SHA-1 is designed to work with messages less than 2^64 bits long.
+ * Although SHA-1 allows a message digest to be generated for
+ * messages of any number of bits less than 2^64, this implementation
+ * only works with messages with a length that is a multiple of 8
+ * bits.
+ *
+ */
+
+
+#include "sha1.h"
+
+/*
+ * SHA1
+ *
+ * Description:
+ * This is the constructor for the sha1 class.
+ *
+ * Parameters:
+ * None.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ *
+ */
+SHA1::SHA1()
+{
+ Reset();
+}
+
+/*
+ * ~SHA1
+ *
+ * Description:
+ * This is the destructor for the sha1 class
+ *
+ * Parameters:
+ * None.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ *
+ */
+SHA1::~SHA1()
+{
+ // The destructor does nothing
+}
+
+/*
+ * Reset
+ *
+ * Description:
+ * This function will initialize the sha1 class member variables
+ * in preparation for computing a new message digest.
+ *
+ * Parameters:
+ * None.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ *
+ */
+void SHA1::Reset()
+{
+ Length_Low = 0;
+ Length_High = 0;
+ Message_Block_Index = 0;
+
+ H[0] = 0x67452301;
+ H[1] = 0xEFCDAB89;
+ H[2] = 0x98BADCFE;
+ H[3] = 0x10325476;
+ H[4] = 0xC3D2E1F0;
+
+ Computed = false;
+ Corrupted = false;
+}
+
+/*
+ * Result
+ *
+ * Description:
+ * This function will return the 160-bit message digest into the
+ * array provided.
+ *
+ * Parameters:
+ * message_digest_array: [out]
+ * This is an array of five unsigned integers which will be filled
+ * with the message digest that has been computed.
+ *
+ * Returns:
+ * True if successful, false if it failed.
+ *
+ * Comments:
+ *
+ */
+bool SHA1::Result(unsigned *message_digest_array)
+{
+ int i; // Counter
+
+ if (Corrupted)
+ {
+ return false;
+ }
+
+ if (!Computed)
+ {
+ PadMessage();
+ Computed = true;
+ }
+
+ for(i = 0; i < 5; i++)
+ {
+ message_digest_array[i] = H[i];
+ }
+
+ return true;
+}
+
+/*
+ * Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion of
+ * the message.
+ *
+ * Parameters:
+ * message_array: [in]
+ * An array of characters representing the next portion of the
+ * message.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ *
+ */
+void SHA1::Input( const unsigned char *message_array,
+ unsigned length)
+{
+ if (!length)
+ {
+ return;
+ }
+
+ if (Computed || Corrupted)
+ {
+ Corrupted = true;
+ return;
+ }
+
+ while(length-- && !Corrupted)
+ {
+ Message_Block[Message_Block_Index++] = (*message_array & 0xFF);
+
+ Length_Low += 8;
+ Length_Low &= 0xFFFFFFFF; // Force it to 32 bits
+ if (Length_Low == 0)
+ {
+ Length_High++;
+ Length_High &= 0xFFFFFFFF; // Force it to 32 bits
+ if (Length_High == 0)
+ {
+ Corrupted = true; // Message is too long
+ }
+ }
+
+ if (Message_Block_Index == 64)
+ {
+ ProcessMessageBlock();
+ }
+
+ message_array++;
+ }
+}
+
+/*
+ * Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion of
+ * the message.
+ *
+ * Parameters:
+ * message_array: [in]
+ * An array of characters representing the next portion of the
+ * message.
+ * length: [in]
+ * The length of the message_array
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ *
+ */
+void SHA1::Input( const char *message_array,
+ unsigned length)
+{
+ Input((unsigned char *) message_array, length);
+}
+
+/*
+ * Input
+ *
+ * Description:
+ * This function accepts a single octets as the next message element.
+ *
+ * Parameters:
+ * message_element: [in]
+ * The next octet in the message.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ *
+ */
+void SHA1::Input(unsigned char message_element)
+{
+ Input(&message_element, 1);
+}
+
+/*
+ * Input
+ *
+ * Description:
+ * This function accepts a single octet as the next message element.
+ *
+ * Parameters:
+ * message_element: [in]
+ * The next octet in the message.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ *
+ */
+void SHA1::Input(char message_element)
+{
+ Input((unsigned char *) &message_element, 1);
+}
+
+/*
+ * operator<<
+ *
+ * Description:
+ * This operator makes it convenient to provide character strings to
+ * the SHA1 object for processing.
+ *
+ * Parameters:
+ * message_array: [in]
+ * The character array to take as input.
+ *
+ * Returns:
+ * A reference to the SHA1 object.
+ *
+ * Comments:
+ * Each character is assumed to hold 8 bits of information.
+ *
+ */
+SHA1& SHA1::operator<<(const char *message_array)
+{
+ const char *p = message_array;
+
+ while(*p)
+ {
+ Input(*p);
+ p++;
+ }
+
+ return *this;
+}
+
+/*
+ * operator<<
+ *
+ * Description:
+ * This operator makes it convenient to provide character strings to
+ * the SHA1 object for processing.
+ *
+ * Parameters:
+ * message_array: [in]
+ * The character array to take as input.
+ *
+ * Returns:
+ * A reference to the SHA1 object.
+ *
+ * Comments:
+ * Each character is assumed to hold 8 bits of information.
+ *
+ */
+SHA1& SHA1::operator<<(const unsigned char *message_array)
+{
+ const unsigned char *p = message_array;
+
+ while(*p)
+ {
+ Input(*p);
+ p++;
+ }
+
+ return *this;
+}
+
+/*
+ * operator<<
+ *
+ * Description:
+ * This function provides the next octet in the message.
+ *
+ * Parameters:
+ * message_element: [in]
+ * The next octet in the message
+ *
+ * Returns:
+ * A reference to the SHA1 object.
+ *
+ * Comments:
+ * The character is assumed to hold 8 bits of information.
+ *
+ */
+SHA1& SHA1::operator<<(const char message_element)
+{
+ Input((unsigned char *) &message_element, 1);
+
+ return *this;
+}
+
+/*
+ * operator<<
+ *
+ * Description:
+ * This function provides the next octet in the message.
+ *
+ * Parameters:
+ * message_element: [in]
+ * The next octet in the message
+ *
+ * Returns:
+ * A reference to the SHA1 object.
+ *
+ * Comments:
+ * The character is assumed to hold 8 bits of information.
+ *
+ */
+SHA1& SHA1::operator<<(const unsigned char message_element)
+{
+ Input(&message_element, 1);
+
+ return *this;
+}
+
+/*
+ * ProcessMessageBlock
+ *
+ * Description:
+ * This function will process the next 512 bits of the message
+ * stored in the Message_Block array.
+ *
+ * Parameters:
+ * None.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ * Many of the variable names in this function, especially the single
+ * character names, were used because those were the names used
+ * in the publication.
+ *
+ */
+void SHA1::ProcessMessageBlock()
+{
+ const unsigned K[] = { // Constants defined for SHA-1
+ 0x5A827999,
+ 0x6ED9EBA1,
+ 0x8F1BBCDC,
+ 0xCA62C1D6
+ };
+ int t; // Loop counter
+ unsigned temp; // Temporary word value
+ unsigned W[80]; // Word sequence
+ unsigned A, B, C, D, E; // Word buffers
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for(t = 0; t < 16; t++)
+ {
+ W[t] = ((unsigned) Message_Block[t * 4]) << 24;
+ W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16;
+ W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8;
+ W[t] |= ((unsigned) Message_Block[t * 4 + 3]);
+ }
+
+ for(t = 16; t < 80; t++)
+ {
+ W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+ }
+
+ A = H[0];
+ B = H[1];
+ C = H[2];
+ D = H[3];
+ E = H[4];
+
+ for(t = 0; t < 20; t++)
+ {
+ temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+ temp &= 0xFFFFFFFF;
+ E = D;
+ D = C;
+ C = CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 20; t < 40; t++)
+ {
+ temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+ temp &= 0xFFFFFFFF;
+ E = D;
+ D = C;
+ C = CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 40; t < 60; t++)
+ {
+ temp = CircularShift(5,A) +
+ ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+ temp &= 0xFFFFFFFF;
+ E = D;
+ D = C;
+ C = CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 60; t < 80; t++)
+ {
+ temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+ temp &= 0xFFFFFFFF;
+ E = D;
+ D = C;
+ C = CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ H[0] = (H[0] + A) & 0xFFFFFFFF;
+ H[1] = (H[1] + B) & 0xFFFFFFFF;
+ H[2] = (H[2] + C) & 0xFFFFFFFF;
+ H[3] = (H[3] + D) & 0xFFFFFFFF;
+ H[4] = (H[4] + E) & 0xFFFFFFFF;
+
+ Message_Block_Index = 0;
+}
+
+/*
+ * PadMessage
+ *
+ * Description:
+ * According to the standard, the message must be padded to an even
+ * 512 bits. The first padding bit must be a '1'. The last 64 bits
+ * represent the length of the original message. All bits in between
+ * should be 0. This function will pad the message according to those
+ * rules by filling the message_block array accordingly. It will also
+ * call ProcessMessageBlock() appropriately. When it returns, it
+ * can be assumed that the message digest has been computed.
+ *
+ * Parameters:
+ * None.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ *
+ */
+void SHA1::PadMessage()
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second block.
+ */
+ if (Message_Block_Index > 55)
+ {
+ Message_Block[Message_Block_Index++] = 0x80;
+ while(Message_Block_Index < 64)
+ {
+ Message_Block[Message_Block_Index++] = 0;
+ }
+
+ ProcessMessageBlock();
+
+ while(Message_Block_Index < 56)
+ {
+ Message_Block[Message_Block_Index++] = 0;
+ }
+ }
+ else
+ {
+ Message_Block[Message_Block_Index++] = 0x80;
+ while(Message_Block_Index < 56)
+ {
+ Message_Block[Message_Block_Index++] = 0;
+ }
+
+ }
+
+ /*
+ * Store the message length as the last 8 octets
+ */
+ Message_Block[56] = static_cast<char>((Length_High >> 24) & 0xFF);
+ Message_Block[57] = static_cast<char>((Length_High >> 16) & 0xFF);
+ Message_Block[58] = static_cast<char>((Length_High >> 8) & 0xFF);
+ Message_Block[59] = static_cast<char>((Length_High) & 0xFF);
+ Message_Block[60] = static_cast<char>((Length_Low >> 24) & 0xFF);
+ Message_Block[61] = static_cast<char>((Length_Low >> 16) & 0xFF);
+ Message_Block[62] = static_cast<char>((Length_Low >> 8) & 0xFF);
+ Message_Block[63] = static_cast<char>((Length_Low) & 0xFF);
+
+ ProcessMessageBlock();
+}
+
+
+/*
+ * CircularShift
+ *
+ * Description:
+ * This member function will perform a circular shifting operation.
+ *
+ * Parameters:
+ * bits: [in]
+ * The number of bits to shift (1-31)
+ * word: [in]
+ * The value to shift (assumes a 32-bit integer)
+ *
+ * Returns:
+ * The shifted value.
+ *
+ * Comments:
+ *
+ */
+unsigned SHA1::CircularShift(int bits, unsigned word)
+{
+ return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits));
+}
diff --git a/lib/sha1.h b/lib/sha1.h
new file mode 100644
index 00000000..de28bbf0
--- /dev/null
+++ b/lib/sha1.h
@@ -0,0 +1,89 @@
+/*
+ * sha1.h
+ *
+ * Copyright (C) 1998
+ * Paul E. Jones <paulej@arid.us>
+ * All Rights Reserved.
+ *
+ *****************************************************************************
+ * $Id: sha1.h,v 1.6 2004/03/27 18:02:26 paulej Exp $
+ *****************************************************************************
+ *
+ * Description:
+ * This class implements the Secure Hashing Standard as defined
+ * in FIPS PUB 180-1 published April 17, 1995.
+ *
+ * Many of the variable names in this class, especially the single
+ * character names, were used because those were the names used
+ * in the publication.
+ *
+ * Please read the file sha1.cpp for more information.
+ *
+ */
+
+#ifndef _SHA1_H_
+#define _SHA1_H_
+
+class SHA1
+{
+
+ public:
+
+ SHA1();
+ virtual ~SHA1();
+
+ /*
+ * Re-initialize the class
+ */
+ void Reset();
+
+ /*
+ * Returns the message digest
+ */
+ bool Result(unsigned *message_digest_array);
+
+ /*
+ * Provide input to SHA1
+ */
+ void Input( const unsigned char *message_array,
+ unsigned length);
+ void Input( const char *message_array,
+ unsigned length);
+ void Input(unsigned char message_element);
+ void Input(char message_element);
+ SHA1& operator<<(const char *message_array);
+ SHA1& operator<<(const unsigned char *message_array);
+ SHA1& operator<<(const char message_element);
+ SHA1& operator<<(const unsigned char message_element);
+
+ private:
+
+ /*
+ * Process the next 512 bits of the message
+ */
+ void ProcessMessageBlock();
+
+ /*
+ * Pads the current message block to 512 bits
+ */
+ void PadMessage();
+
+ /*
+ * Performs a circular left shift operation
+ */
+ inline unsigned CircularShift(int bits, unsigned word);
+
+ unsigned H[5]; // Message digest buffers
+
+ unsigned Length_Low; // Message length in bits
+ unsigned Length_High; // Message length in bits
+
+ unsigned char Message_Block[64]; // 512-bit message blocks
+ int Message_Block_Index; // Index into message block array
+
+ bool Computed; // Is the digest computed?
+ bool Corrupted; // Is the message digest corruped?
+
+};
+
+#endif
diff --git a/lib/utfcpp b/lib/utfcpp
new file mode 160000
+Subproject 200cf64535a8a2545414e993349f6c87c8dd64b
diff --git a/ledger.el b/lisp/ledger.el
index 6262ec94..8e4de270 100644
--- a/ledger.el
+++ b/lisp/ledger.el
@@ -1,10 +1,10 @@
;;; ledger.el --- Helper code for use with the "ledger" command-line tool
-;; Copyright (C) 2008 John Wiegley (johnw AT gnu DOT org)
+;; Copyright (C) 2003-2009 John Wiegley (johnw AT gnu DOT org)
;; Emacs Lisp Archive Entry
;; Filename: ledger.el
-;; Version: 2.6.1
+;; Version: 3.0
;; Date: Fri 18-Jul-2008
;; Keywords: data
;; Author: John Wiegley (johnw AT gnu DOT org)
@@ -49,8 +49,7 @@
;;
;; In the reconcile buffer, use SPACE to toggle the cleared status of
;; a transaction, C-x C-s to save changes (to the ledger file as
-;; well), or C-c C-r to attempt an auto-reconcilation based on the
-;; statement's ending date and balance.
+;; well).
;;
;; The ledger reports command asks the user to select a report to run
;; then creates a report buffer containing the results of running the
@@ -129,11 +128,17 @@ text that should replace the format specifier."
(defvar bold 'bold)
(defvar ledger-font-lock-keywords
- `((,(concat "^[0-9/.=-]+\\(\\s-+\\*\\)?\\(\\s-+(.*?)\\)?\\s-+"
- "\\(.+?\\)\\(\t\\|\n\\| [ \t]\\)") 3 bold)
- (";.+" . font-lock-comment-face)
- ("^\\s-+.+?\\( \\|\t\\|\n\\|\\s-+$\\)" . font-lock-keyword-face))
- "Default expressions to highlight in Ledger mode.")
+ '(("\\( \\| \\|^\\)\\(;.*\\)" 2 font-lock-comment-face)
+ ("^[0-9]+[-/.=][-/.=0-9]+\\s-+\\(([^)]+)\\s-+\\)?\\([^*].+?\\)\\(\\( ;\\| ;\\|$\\)\\)" 2 bold)
+ ;;("^[0-9]+[-/.=][-/.=0-9]+\\s-+\\(([^)]+)\\s-+\\)?\\([*].+?\\)\\(\\( ;\\| ;\\|$\\)\\)"
+ ;; 2 font-lock-type-face)
+ ("^\\s-+\\([*]\\s-*\\)?\\(\\([[(]\\)?[^*:
+ ]+?:[^]);
+ ]+?\\([])]\\)?\\)\\( \\| \\|$\\)"
+ 2 font-lock-keyword-face)
+ ("^\\([~=].+\\)" 1 font-lock-function-name-face)
+ ("^\\([A-Za-z]+ .+\\)" 1 font-lock-function-name-face))
+ "Expressions to highlight in Ledger mode.")
(defsubst ledger-current-year ()
(format-time-string "%Y"))
@@ -195,38 +200,34 @@ Return the difference in the format of a time value."
(if (ledger-time-less-p moment date)
(throw 'found t)))))))
-(defun ledger-add-entry (entry-text)
+(defun ledger-add-entry (entry-text &optional insert-at-point)
(interactive
(list
(read-string "Entry: " (concat ledger-year "/" ledger-month "/"))))
(let* ((args (with-temp-buffer
(insert entry-text)
(eshell-parse-arguments (point-min) (point-max))))
- (date (car args))
- (insert-year t)
(ledger-buf (current-buffer))
exit-code)
- (if (string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" date)
- (setq date
- (encode-time 0 0 0 (string-to-number (match-string 3 date))
- (string-to-number (match-string 2 date))
- (string-to-number (match-string 1 date)))))
- (ledger-find-slot date)
- (save-excursion
- (if (re-search-backward "^Y " nil t)
- (setq insert-year nil)))
+ (unless insert-at-point
+ (let ((date (car args)))
+ (if (string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" date)
+ (setq date
+ (encode-time 0 0 0 (string-to-number (match-string 3 date))
+ (string-to-number (match-string 2 date))
+ (string-to-number (match-string 1 date)))))
+ (ledger-find-slot date)))
(save-excursion
(insert
(with-temp-buffer
(setq exit-code
(apply #'ledger-run-ledger ledger-buf "entry"
(mapcar 'eval args)))
- (if (= 0 exit-code)
- (if insert-year
- (buffer-substring 2 (point-max))
- (buffer-substring 7 (point-max)))
- (concat (if insert-year entry-text
- (substring entry-text 6)) "\n"))) "\n"))))
+ (goto-char (point-min))
+ (if (looking-at "Error: ")
+ (error (buffer-string))
+ (buffer-string)))
+ "\n"))))
(defun ledger-current-entry-bounds ()
(save-excursion
@@ -412,8 +413,20 @@ dropped."
(defun ledger-toggle-current (&optional style)
(interactive)
- (if ledger-clear-whole-entries
- (ledger-toggle-current-entry style)
+ (if (or ledger-clear-whole-entries
+ (eq 'entry (ledger-thing-at-point)))
+ (progn
+ (save-excursion
+ (forward-line)
+ (goto-char (line-beginning-position))
+ (while (and (not (eolp))
+ (save-excursion
+ (not (eq 'entry (ledger-thing-at-point)))))
+ (if (looking-at "\\s-+[*!]")
+ (ledger-toggle-current-transaction nil))
+ (forward-line)
+ (goto-char (line-beginning-position))))
+ (ledger-toggle-current-entry style))
(ledger-toggle-current-transaction style)))
(defvar ledger-mode-abbrev-table)
@@ -480,7 +493,7 @@ dropped."
(account ledger-acct)
(inhibit-read-only t)
cleared)
- (when (equal (car where) "<stdin>")
+ (when (or (equal (car where) "<stdin>") (equal (car where) "/dev/stdin"))
(with-current-buffer ledger-buf
(goto-char (cdr where))
(setq cleared (ledger-toggle-current 'pending)))
@@ -493,40 +506,6 @@ dropped."
(list 'face))))
(forward-line)))
-(defun ledger-auto-reconcile (balance date)
- (interactive "sReconcile to balance (negative for a liability): \nsStatement date (default: now): ")
- (let ((buffer ledger-buf)
- (account ledger-acct) cleared)
- ;; attempt to auto-reconcile in the background
- (with-temp-buffer
- (let ((exit-code
- (ledger-run-ledger buffer "--format" "%xb\\n"
- "--reconcile" balance "--reconcile-date" date
- "register" account)))
- (if (/= 0 exit-code)
- (error "Failed to reconcile account '%s' to balance '%s'"
- account balance)
- (goto-char (point-min))
- (unless (looking-at "[0-9]")
- (error (buffer-string)))
- (while (not (eobp))
- (push (read (current-buffer)) cleared)
- (forward-line)))))
- (goto-char (point-min))
- (with-current-buffer ledger-buf
- (setq cleared (mapcar (lambda (line)
- (goto-line line)
- (point-marker))
- (nreverse cleared))))
- (let ((inhibit-redisplay t))
- (dolist (pos cleared)
- (while (and (not (eobp))
- (/= pos (cdr (get-text-property (point) 'where))))
- (forward-line))
- (unless (eobp)
- (ledger-reconcile-toggle))))
- (goto-char (point-min))))
-
(defun ledger-reconcile-refresh ()
(interactive)
(let ((inhibit-read-only t)
@@ -553,7 +532,7 @@ dropped."
(defun ledger-reconcile-delete ()
(interactive)
(let ((where (get-text-property (point) 'where)))
- (when (equal (car where) "<stdin>")
+ (when (or (equal (car where) "<stdin>") (equal (car where) "/dev/stdin"))
(with-current-buffer ledger-buf
(goto-char (cdr where))
(ledger-delete-current-entry))
@@ -565,7 +544,7 @@ dropped."
(defun ledger-reconcile-visit ()
(interactive)
(let ((where (get-text-property (point) 'where)))
- (when (equal (car where) "<stdin>")
+ (when (or (equal (car where) "<stdin>") (equal (car where) "/dev/stdin"))
(switch-to-buffer-other-window ledger-buf)
(goto-char (cdr where)))))
@@ -588,7 +567,7 @@ dropped."
(let ((where (get-text-property (point) 'where))
(face (get-text-property (point) 'face)))
(if (and (eq face 'bold)
- (equal (car where) "<stdin>"))
+ (or (equal (car where) "<stdin>") (equal (car where) "/dev/stdin")))
(with-current-buffer ledger-buf
(goto-char (cdr where))
(ledger-toggle-current 'cleared))))
@@ -616,9 +595,13 @@ dropped."
(with-current-buffer buf
(cons
(nth 0 item)
- (save-excursion
- (goto-line (nth 0 xact))
- (point-marker))))))
+ (if ledger-clear-whole-entries
+ (save-excursion
+ (goto-line (nth 1 item))
+ (point-marker))
+ (save-excursion
+ (goto-line (nth 0 xact))
+ (point-marker)))))))
(insert (format "%s %-30s %-25s %15s\n"
(format-time-string "%m/%d" (nth 2 item))
(nth 4 item) (nth 1 xact) (nth 2 xact)))
@@ -633,8 +616,8 @@ dropped."
(set-buffer-modified-p nil)
(toggle-read-only t)))
-(defun ledger-reconcile (account &optional arg)
- (interactive "sAccount to reconcile: \nP")
+(defun ledger-reconcile (account)
+ (interactive "sAccount to reconcile: ")
(let ((buf (current-buffer))
(rbuf (get-buffer "*Reconcile*")))
(if rbuf
@@ -645,10 +628,7 @@ dropped."
(ledger-reconcile-mode)
(set (make-local-variable 'ledger-buf) buf)
(set (make-local-variable 'ledger-acct) account)
- (ledger-do-reconcile)
- (when arg
- (sit-for 0 0)
- (call-interactively #'ledger-auto-reconcile)))))
+ (ledger-do-reconcile))))
(defvar ledger-reconcile-mode-abbrev-table)
@@ -658,7 +638,6 @@ dropped."
(define-key map [(control ?m)] 'ledger-reconcile-visit)
(define-key map [return] 'ledger-reconcile-visit)
(define-key map [(control ?c) (control ?c)] 'ledger-reconcile-finish)
- (define-key map [(control ?c) (control ?r)] 'ledger-auto-reconcile)
(define-key map [(control ?x) (control ?s)] 'ledger-reconcile-save)
(define-key map [(control ?l)] 'ledger-reconcile-refresh)
(define-key map [? ] 'ledger-reconcile-toggle)
@@ -666,7 +645,6 @@ dropped."
(define-key map [?d] 'ledger-reconcile-delete)
(define-key map [?n] 'next-line)
(define-key map [?p] 'previous-line)
- (define-key map [?r] 'ledger-auto-reconcile)
(define-key map [?s] 'ledger-reconcile-save)
(define-key map [?q] 'ledger-reconcile-quit)
(use-local-map map)))
@@ -833,6 +811,7 @@ specified line, returns nil."
"A mode for viewing ledger reports."
(let ((map (make-sparse-keymap)))
(define-key map [? ] 'scroll-up)
+ (define-key map [backspace] 'scroll-down)
(define-key map [?r] 'ledger-report-redo)
(define-key map [?s] 'ledger-report-save)
(define-key map [?k] 'ledger-report-kill)
@@ -890,7 +869,10 @@ used to generate the buffer, navigating the buffer, etc."
(set (make-local-variable 'ledger-report-name) report-name)
(set (make-local-variable 'ledger-original-window-cfg) wcfg)
(ledger-do-report (ledger-report-cmd report-name edit))
- (shrink-window-if-larger-than-buffer))))
+ (shrink-window-if-larger-than-buffer)
+ (set-buffer-modified-p nil)
+ (setq buffer-read-only t)
+ (message "q to quit; r to redo; e to edit; k to kill; s to save; SPC and DEL to scroll"))))
(defun string-empty-p (s)
"Check for the empty string."
@@ -992,7 +974,8 @@ the default."
(defun ledger-do-report (cmd)
"Run a report command line."
(goto-char (point-min))
- (insert (format "Report: %s\n" cmd)
+ (insert (format "Report: %s\n" ledger-report-name)
+ (format "Command: %s\n" cmd)
(make-string (- (window-width) 1) ?=)
"\n")
(shell-command cmd t nil))
@@ -1010,14 +993,17 @@ the default."
"Redo the report in the current ledger report buffer."
(interactive)
(ledger-report-goto)
+ (setq buffer-read-only nil)
(erase-buffer)
- (ledger-do-report ledger-report-cmd))
+ (ledger-do-report ledger-report-cmd)
+ (setq buffer-read-only nil))
(defun ledger-report-quit ()
- "Quit the ledger report buffer."
+ "Quit the ledger report buffer by burying it."
(interactive)
(ledger-report-goto)
- (set-window-configuration ledger-original-window-cfg))
+ (set-window-configuration ledger-original-window-cfg)
+ (bury-buffer (get-buffer ledger-report-buffer-name)))
(defun ledger-report-kill ()
"Kill the ledger report buffer."
@@ -1072,6 +1058,9 @@ the default."
((looking-at "^\\s-+\\([*!]\\s-+\\)?[[(]?\\(.\\)")
(goto-char (match-beginning 2))
'transaction)
+ ((looking-at "^\\(sun\\|mon\\|tue\\|wed\\|thu\\|fri\\|sat\\)\\s-+")
+ (goto-char (match-end 0))
+ 'entry)
(t
(ignore (goto-char here))))))
@@ -1162,7 +1151,22 @@ the default."
(while (pcomplete-here
(if (eq (save-excursion
(ledger-thing-at-point)) 'entry)
- (ledger-entries)
+ (if (null current-prefix-arg)
+ (ledger-entries) ; this completes against entry names
+ (progn
+ (let ((text (buffer-substring (line-beginning-position)
+ (line-end-position))))
+ (delete-region (line-beginning-position)
+ (line-end-position))
+ (condition-case err
+ (ledger-add-entry text t)
+ ((error)
+ (insert text))))
+ (forward-line)
+ (goto-char (line-end-position))
+ (search-backward ";" (line-beginning-position) t)
+ (skip-chars-backward " \t0123456789.,")
+ (throw 'pcompleted t)))
(ledger-accounts)))))
(defun ledger-fully-complete-entry ()
@@ -1265,11 +1269,13 @@ This is done so that the last digit falls in COLUMN, which defaults to 52."
(t
(let ((buf (current-buffer)))
(with-current-buffer buffer
- (apply #'call-process-region
- (append (list (point-min) (point-max)
- ledger-binary-path ledger-delete-after
- buf nil "-f" "-")
- args)))))))
+ (let ((coding-system-for-write 'utf-8)
+ (coding-system-for-read 'utf-8))
+ (apply #'call-process-region
+ (append (list (point-min) (point-max)
+ ledger-binary-path ledger-delete-after
+ buf nil "-f" "-")
+ args))))))))
(defun ledger-run-ledger-and-delete (buffer &rest args)
(let ((ledger-delete-after t))
diff --git a/timeclock.el b/lisp/timeclock.el
index 03159e94..03159e94 100644
--- a/timeclock.el
+++ b/lisp/timeclock.el
diff --git a/main.cc b/main.cc
deleted file mode 100644
index 02a06f0c..00000000
--- a/main.cc
+++ /dev/null
@@ -1,496 +0,0 @@
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <algorithm>
-#include <exception>
-#include <iterator>
-#include <string>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-
-#include "acconf.h"
-
-#ifdef HAVE_UNIX_PIPES
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include "fdstream.hpp"
-#endif
-
-#include "ledger.h"
-
-using namespace ledger;
-
-int parse_and_report(config_t& config, std::auto_ptr<journal_t>& journal,
- report_t& report, int argc, char * argv[], char * envp[])
-{
- // Configure the terminus for value expressions
-
- ledger::terminus = datetime_t::now;
-
- // Parse command-line arguments, and those set in the environment
-
- std::list<std::string> args;
- process_arguments(ledger::config_options, argc - 1, argv + 1, false, args);
-
- if (args.empty()) {
- option_help(std::cerr);
- return 1;
- }
- strings_list::iterator arg = args.begin();
-
- if (config.cache_file == "<none>")
- config.use_cache = false;
- else
- config.use_cache = config.data_file.empty() && config.price_db.empty();
- DEBUG_PRINT("ledger.config.cache", "1. use_cache = " << config.use_cache);
-
- TRACE(main, "Processing options and environment variables");
-
- process_environment(ledger::config_options,
- const_cast<const char **>(envp), "LEDGER_");
-
-#if 1
- // These are here for backwards compatability, but are deprecated.
-
- if (const char * p = std::getenv("LEDGER"))
- process_option(ledger::config_options, "file", p);
- if (const char * p = std::getenv("LEDGER_INIT"))
- process_option(ledger::config_options, "init-file", p);
- if (const char * p = std::getenv("PRICE_HIST"))
- process_option(ledger::config_options, "price-db", p);
- if (const char * p = std::getenv("PRICE_EXP"))
- process_option(ledger::config_options, "price-exp", p);
-#endif
-
- const char * p = std::getenv("HOME");
- std::string home = p ? p : "";
-
- if (config.init_file.empty())
- config.init_file = home + "/.ledgerrc";
- if (config.price_db.empty())
- config.price_db = home + "/.pricedb";
-
- if (config.cache_file.empty())
- config.cache_file = home + "/.ledger-cache";
-
- if (config.data_file == config.cache_file)
- config.use_cache = false;
- DEBUG_PRINT("ledger.config.cache", "2. use_cache = " << config.use_cache);
-
- TRACE(main, std::string("Initialization file is ") + config.init_file);
- TRACE(main, std::string("Price database is ") + config.price_db);
- TRACE(main, std::string("Binary cache is ") + config.cache_file);
- TRACE(main, std::string("Main journal is ") + config.data_file);
-
- TRACE(main, std::string("Based on option settings, binary cache ") +
- (config.use_cache ? "WILL " : "will NOT ") + "be used");
-
- // Read the command word, canonicalize it to its one letter form,
- // then configure the system based on the kind of report to be
- // generated
-
- std::string command = *arg++;
-
- if (command == "balance" || command == "bal" || command == "b")
- command = "b";
- else if (command == "register" || command == "reg" || command == "r")
- command = "r";
- else if (command == "print" || command == "p")
- command = "p";
- else if (command == "output")
- command = "w";
- else if (command == "dump")
- command = "W";
- else if (command == "emacs" || command == "lisp")
- command = "x";
- else if (command == "xml")
- command = "X";
- else if (command == "entry")
- command = "e";
- else if (command == "equity")
- command = "E";
- else if (command == "prices")
- command = "P";
- else if (command == "pricesdb")
- command = "D";
- else if (command == "csv")
- command = "c";
- else if (command == "parse") {
- value_expr expr(ledger::parse_value_expr(*arg));
-
- if (config.verbose_mode) {
- std::cout << "Value expression tree:" << std::endl;
- ledger::dump_value_expr(std::cout, expr.get());
- std::cout << std::endl;
- std::cout << "Value expression parsed was:" << std::endl;
- ledger::write_value_expr(std::cout, expr.get());
- std::cout << std::endl << std::endl;
- std::cout << "Result of computation: ";
- }
-
- value_t result = guarded_compute(expr.get());
- std::cout << result.strip_annotations() << std::endl;
-
- return 0;
- }
- else if (command == "expr") {
- // this gets done below...
- }
- else {
- throw new error(std::string("Unrecognized command '") + command + "'");
- }
-
- // Parse initialization files, ledger data, price database, etc.
-
- journal.reset(new journal_t);
-
- { TRACE_PUSH(parser, "Parsing journal file");
-
- if (parse_ledger_data(config, journal.get()) == 0)
- throw new error("Please specify ledger file using -f"
- " or LEDGER_FILE environment variable.");
-
- TRACE_POP(parser, "Finished parsing"); }
-
- // process the command word and its following arguments
-
- std::string first_arg;
- if (command == "w") {
- if (arg != args.end())
- first_arg = *arg++;
- }
- else if (command == "W") {
- if (report.output_file.empty())
- throw new error("The 'dump' command requires use of the --output option");
- }
-
- TRACE(options, std::string("Post-processing options ") +
- "for command \"" + command + "\"");
-
- report.process_options(command, arg, args.end());
-
- // If downloading is to be supported, configure the updater
-
- if (! commodity_base_t::updater && config.download_quotes)
- commodity_base_t::updater =
- new quotes_by_script(config.price_db, config.pricing_leeway,
- config.cache_dirty);
-
- std::auto_ptr<entry_t> new_entry;
- if (command == "e") {
- if (arg == args.end()) {
- std::cout << "\
-The entry command requires at least one argument, so Ledger can intelligently\n\
-create a new entry for you. The possible arguments are:\n\
- DATE PAYEE [ACCOUNT] [AMOUNT] [DRAW ACCOUNT]\n\n\
-Some things to note:\n\
- - The ACCOUNT is optional; if no account is given, the last account affected\n\
- by PAYEE is used. If no payee can be found, the generic account 'Expenses'\n\
- is used.\n\
- - The AMOUNT is optional; if not specified, the same amount is used as the\n\
- last time PAYEE was seen, or 0 if not applicable.\n\
- - The AMOUNT does not require a commodity; if none is given, the commodity\n\
- currently contained within ACCOUNT is used, or no commodity at all if\n\
- either: the ACCOUNT was not found, or it contains more than one commodity.\n\
- - Lastly, the DRAW ACCOUNT is optional; if not present, the last account\n\
- drawn from by PAYEE is used, or the 'basket' account (specified with\n\
- 'A ACCOUNT' in your Ledger file) if that does not apply, or the generic\n\
- account 'Equity' is used.\n\n\
-Here are a few examples, all of which may be equivalent depending on your\n\
-Ledger data:\n\
- ledger entry 3/25 chevron\n\
- ledger entry 3/25 chevron 20\n\
- ledger entry 3/25 chevron \\$20\n\
- ledger entry 3/25 chevron gas 20\n\
- ledger entry 3/25 chevron gas \\$20 checking\n\n\
-A final note: Ledger never modifies your data! You are responsible for\n\
-appending the output of this command to your Ledger file if you so choose."
- << std::endl;
- return 1;
- }
- new_entry.reset(derive_new_entry(*journal, arg, args.end()));
- if (! new_entry.get())
- return 1;
- }
-
- // Configure the output stream
-
-#ifdef HAVE_UNIX_PIPES
- int status, pfd[2]; // Pipe file descriptors
-#endif
- std::ostream * out = &std::cout;
-
- if (! report.output_file.empty()) {
- out = new std::ofstream(report.output_file.c_str());
- }
-#ifdef HAVE_UNIX_PIPES
- else if (! config.pager.empty()) {
- status = pipe(pfd);
- if (status == -1)
- throw new error("Failed to create pipe");
-
- status = fork();
- if (status < 0) {
- throw new error("Failed to fork child process");
- }
- else if (status == 0) { // child
- const char *arg0;
-
- // Duplicate pipe's reading end into stdin
- status = dup2(pfd[0], STDIN_FILENO);
- if (status == -1)
- perror("dup2");
-
- // Close unuseful file descriptors: the pipe's writing and
- // reading ends (the latter is not needed anymore, after the
- // duplication).
- close(pfd[1]);
- close(pfd[0]);
-
- // Find command name: its the substring starting right of the
- // rightmost '/' character in the pager pathname. See manpage
- // for strrchr.
- arg0 = std::strrchr(config.pager.c_str(), '/');
- if (arg0)
- arg0++;
- else
- arg0 = config.pager.c_str(); // No slashes in pager.
-
- execlp(config.pager.c_str(), arg0, (char *)0);
- perror("execl");
- exit(1);
- }
- else { // parent
- close(pfd[0]);
- out = new boost::fdostream(pfd[1]);
- }
- }
-#endif
-
- // Are we handling the parse or expr commands? Do so now.
-
- if (command == "expr") {
- value_expr expr(ledger::parse_value_expr(*arg));
-
- if (config.verbose_mode) {
- std::cout << "Value expression tree:" << std::endl;
- ledger::dump_value_expr(std::cout, expr.get());
- std::cout << std::endl;
- std::cout << "Value expression parsed was:" << std::endl;
- ledger::write_value_expr(std::cout, expr.get());
- std::cout << std::endl << std::endl;
- std::cout << "Result of computation: ";
- }
-
- value_t result = guarded_compute(expr.get());
- std::cout << result.strip_annotations() << std::endl;
-
- return 0;
- }
-
- // Compile the format strings
-
- const std::string * format;
-
- if (! report.format_string.empty())
- format = &report.format_string;
- else if (command == "b")
- format = &config.balance_format;
- else if (command == "r")
- format = &config.register_format;
- else if (command == "E")
- format = &config.equity_format;
- else if (command == "P")
- format = &config.prices_format;
- else if (command == "D")
- format = &config.pricesdb_format;
- else if (command == "w")
- format = &config.write_xact_format;
- else
- format = &config.print_format;
-
- // Walk the entries based on the report type and the options
-
- item_handler<transaction_t> * formatter;
- std::list<item_handler<transaction_t> *> formatter_ptrs;
-
- if (command == "b" || command == "E")
- formatter = new set_account_value;
- else if (command == "p" || command == "e")
- formatter = new format_entries(*out, *format);
- else if (command == "x")
- formatter = new format_emacs_transactions(*out);
- else if (command == "X")
- formatter = new format_xml_entries(*out, report.show_totals);
- else if (command == "c")
- formatter = new format_csv_transactions(*out);
- else
- formatter = new format_transactions(*out, *format);
-
- if (command == "w") {
- TRACE_PUSH(text_writer, "Writing journal file");
- write_textual_journal(*journal, first_arg, *formatter,
- config.write_hdr_format, *out);
- TRACE_POP(text_writer, "Finished writing");
- }
- else if (command == "W") {
- TRACE_PUSH(binary_writer, "Writing binary file");
- std::ofstream stream(report.output_file.c_str());
- write_binary_journal(stream, journal.get());
- TRACE_POP(binary_writer, "Finished writing");
- }
- else {
- TRACE_PUSH(main, "Walking journal entries");
-
- formatter = report.chain_xact_handlers(command, formatter, journal.get(),
- journal->master, formatter_ptrs);
- if (command == "e")
- walk_transactions(new_entry->transactions, *formatter);
- else if (command == "P" || command == "D")
- walk_commodities(commodity_t::commodities, *formatter);
- else
- walk_entries(journal->entries, *formatter);
-
- if (command != "P" && command != "D")
- formatter->flush();
-
- TRACE_POP(main, "Finished entry walk");
- }
-
- // For the balance and equity reports, output the sum totals.
-
- if (command == "b") {
- TRACE_PUSH(main, "Walking journal accounts");
-
- format_account acct_formatter(*out, *format, report.display_predicate);
- sum_accounts(*journal->master);
- walk_accounts(*journal->master, acct_formatter, report.sort_string);
- acct_formatter.flush();
-
- if (account_has_xdata(*journal->master)) {
- account_xdata_t& xdata = account_xdata(*journal->master);
- if (! report.show_collapsed && xdata.total) {
- *out << "--------------------\n";
- xdata.value = xdata.total;
- acct_formatter.format.format(*out, details_t(*journal->master));
- }
- }
- TRACE_POP(main, "Finished account walk");
- }
- else if (command == "E") {
- TRACE_PUSH(main, "Walking journal accounts");
-
- format_equity acct_formatter(*out, *format, report.display_predicate);
- sum_accounts(*journal->master);
- walk_accounts(*journal->master, acct_formatter, report.sort_string);
- acct_formatter.flush();
-
- TRACE_POP(main, "Finished account walk");
- }
-
-#if DEBUG_LEVEL >= BETA
- { TRACE_PUSH(cleanup, "Cleaning up allocated memory");
-
- clear_transaction_xdata xact_cleaner;
- walk_entries(journal->entries, xact_cleaner);
-
- clear_account_xdata acct_cleaner;
- walk_accounts(*journal->master, acct_cleaner);
-
- if (! report.output_file.empty())
- delete out;
-
- for (std::list<item_handler<transaction_t> *>::iterator i
- = formatter_ptrs.begin();
- i != formatter_ptrs.end();
- i++)
- delete *i;
-
- TRACE_POP(cleanup, "Finished cleaning"); }
-#endif
-
- // Write out the binary cache, if need be
-
- if (config.use_cache && config.cache_dirty &&
- ! config.cache_file.empty()) {
- TRACE_PUSH(binary_cache, "Writing journal file");
-
- std::ofstream stream(config.cache_file.c_str());
- write_binary_journal(stream, journal.get());
-
- TRACE_POP(binary_cache, "Finished writing");
- }
-
-#ifdef HAVE_UNIX_PIPES
- if (! config.pager.empty()) {
- delete out;
- close(pfd[1]);
-
- // Wait for child to finish
- wait(&status);
- if (status & 0xffff != 0)
- throw new error("Something went wrong in the pager");
- }
-#endif
-
- return 0;
-}
-
-int main(int argc, char * argv[], char * envp[])
-{
- // This variable must be defined here so that any memory it holds is still
- // available should the subsequent exception handlers catch an inner
- // exception and need to report something on the invalid state of the
- // journal (such as an unbalanced entry).
- std::auto_ptr<journal_t> journal;
-
- try {
- std::ios::sync_with_stdio(false);
-
-#if DEBUG_LEVEL < BETA
- ledger::do_cleanup = false;
-#endif
- config_t config;
- report_t report;
- ledger::config = &config;
- ledger::report = &report;
- TRACE_PUSH(main, "Ledger starting");
- int status = parse_and_report(config, journal, report, argc, argv, envp);
- TRACE_POP(main, "Ledger done");
- return status;
- }
- catch (error * err) {
- std::cout.flush();
- // Push a null here since there's no file context
- if (err->context.empty() ||
- ! dynamic_cast<xact_context *>(err->context.front()))
- err->context.push_front(new error_context(""));
- err->reveal_context(std::cerr, "Error");
- std::cerr << err->what() << std::endl;
- delete err;
- return 1;
- }
- catch (fatal * err) {
- std::cout.flush();
- // Push a null here since there's no file context
- if (err->context.empty() ||
- ! dynamic_cast<xact_context *>(err->context.front()))
- err->context.push_front(new error_context(""));
- err->reveal_context(std::cerr, "Fatal");
- std::cerr << err->what() << std::endl;
- delete err;
- return 1;
- }
- catch (const std::exception& err) {
- std::cout.flush();
- std::cerr << "Error: " << err.what() << std::endl;
- return 1;
- }
- catch (int status) {
- return status;
- }
-}
-
-// main.cc ends here.
diff --git a/mask.cc b/mask.cc
deleted file mode 100644
index 972b24ce..00000000
--- a/mask.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "mask.h"
-#include "debug.h"
-#include "util.h"
-
-#include <cstdlib>
-
-#include <pcre.h>
-
-mask_t::mask_t(const std::string& pat) : exclude(false)
-{
- const char * p = pat.c_str();
- if (*p == '-') {
- exclude = true;
- p++;
- while (std::isspace(*p))
- p++;
- }
- else if (*p == '+') {
- p++;
- while (std::isspace(*p))
- p++;
- }
- pattern = p;
-
- const char *error;
- int erroffset;
- regexp = pcre_compile(pattern.c_str(), PCRE_CASELESS,
- &error, &erroffset, NULL);
- if (! regexp)
- throw new mask_error(std::string("Failed to compile regexp '") +
- pattern + "'");
-}
-
-mask_t::mask_t(const mask_t& m) : exclude(m.exclude), pattern(m.pattern)
-{
- const char *error;
- int erroffset;
- regexp = pcre_compile(pattern.c_str(), PCRE_CASELESS,
- &error, &erroffset, NULL);
- assert(regexp);
-}
-
-mask_t::~mask_t() {
- pcre_free((pcre *)regexp);
-}
-
-bool mask_t::match(const std::string& str) const
-{
- static int ovec[30];
- int result = pcre_exec((pcre *)regexp, NULL,
- str.c_str(), str.length(), 0, 0, ovec, 30);
- return result >= 0 && ! exclude;
-}
diff --git a/mask.h b/mask.h
deleted file mode 100644
index 6d4790a3..00000000
--- a/mask.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _MASK_H
-#define _MASK_H
-
-#include <string>
-#include <exception>
-
-#include "error.h"
-
-class mask_t
-{
- public:
- bool exclude;
- std::string pattern;
- void * regexp;
-
- explicit mask_t(const std::string& pattern);
- mask_t(const mask_t&);
- ~mask_t();
-
- bool match(const std::string& str) const;
-};
-
-class mask_error : public error {
- public:
- mask_error(const std::string& reason) throw() : error(reason) {}
- virtual ~mask_error() throw() {}
-};
-
-#endif // _MASK_H
diff --git a/ofx.cc b/ofx.cc
deleted file mode 100644
index 8b53b284..00000000
--- a/ofx.cc
+++ /dev/null
@@ -1,226 +0,0 @@
-#include "journal.h"
-#include "ofx.h"
-#include "format.h"
-#include "datetime.h"
-#include "error.h"
-#include "debug.h"
-#include "util.h"
-
-#include <libofx.h>
-
-namespace ledger {
-
-typedef std::map<const std::string, account_t *> accounts_map;
-typedef std::pair<const std::string, account_t *> accounts_pair;
-
-typedef std::map<const std::string, commodity_t *> commodities_map;
-typedef std::pair<const std::string, commodity_t *> commodities_pair;
-
-journal_t * curr_journal;
-accounts_map ofx_accounts;
-commodities_map ofx_account_currencies;
-commodities_map ofx_securities;
-account_t * master_account;
-
-int ofx_proc_statement_cb(struct OfxStatementData data, void * statement_data)
-{
-}
-
-int ofx_proc_account_cb(struct OfxAccountData data, void * account_data)
-{
- if (! data.account_id_valid)
- return -1;
-
- DEBUG_PRINT("ledger.ofx.parse", "account " << data.account_name);
- account_t * account = new account_t(master_account, data.account_name);
- curr_journal->add_account(account);
- ofx_accounts.insert(accounts_pair(data.account_id, account));
-
- if (data.currency_valid) {
- commodity_t * commodity = commodity_t::find_or_create(data.currency);
- commodity->add_flags(COMMODITY_STYLE_SUFFIXED | COMMODITY_STYLE_SEPARATED);
-
- commodities_map::iterator i = ofx_account_currencies.find(data.account_id);
- if (i == ofx_account_currencies.end())
- ofx_account_currencies.insert(commodities_pair(data.account_id,
- commodity));
- }
-
- return 0;
-}
-
-int ofx_proc_transaction_cb(struct OfxTransactionData data,
- void * transaction_data)
-{
- if (! data.account_id_valid || ! data.units_valid)
- return -1;
-
- accounts_map::iterator i = ofx_accounts.find(data.account_id);
- assert(i != ofx_accounts.end());
- account_t * account = (*i).second;
-
- entry_t * entry = new entry_t;
-
- entry->add_transaction(new transaction_t(account));
- transaction_t * xact = entry->transactions.back();
-
- // get the account's default currency
- commodities_map::iterator ac = ofx_account_currencies.find(data.account_id);
- assert(ac != ofx_account_currencies.end());
- commodity_t * default_commodity = (*ac).second;
-
- std::ostringstream stream;
- stream << - data.units;
-
- // jww (2005-02-09): what if the amount contains fees?
-
- if (data.unique_id_valid) {
- commodities_map::iterator s = ofx_securities.find(data.unique_id);
- assert(s != ofx_securities.end());
- xact->amount = stream.str() + " " + (*s).second->base_symbol();
- } else {
- xact->amount = stream.str() + " " + default_commodity->base_symbol();
- }
-
- if (data.unitprice_valid && data.unitprice != 1.0) {
- std::ostringstream cstream;
- stream << - data.unitprice;
- xact->cost = new amount_t(stream.str() + " " + default_commodity->base_symbol());
- }
-
- DEBUG_PRINT("ledger.ofx.parse", "xact " << xact->amount
- << " from " << *xact->account);
-
- if (data.date_initiated_valid)
- entry->_date = data.date_initiated;
- else if (data.date_posted_valid)
- entry->_date = data.date_posted;
-
- if (data.check_number_valid)
- entry->code = data.check_number;
- else if (data.reference_number_valid)
- entry->code = data.reference_number;
-
- if (data.name_valid)
- entry->payee = data.name;
-
- if (data.memo_valid)
- xact->note = data.memo;
-
- // jww (2005-02-09): check for fi_id_corrected? or is this handled
- // by the library?
-
- // Balance all entries into <Unknown>, since it is not specified.
- account = curr_journal->find_account("<Unknown>");
- entry->add_transaction(new transaction_t(account));
-
- if (! curr_journal->add_entry(entry)) {
- print_entry(std::cerr, *entry);
- // jww (2005-02-09): uncomment
- //have_error = "The above entry does not balance";
- delete entry;
- return -1;
- }
- return 0;
-}
-
-int ofx_proc_security_cb(struct OfxSecurityData data, void * security_data)
-{
- if (! data.unique_id_valid)
- return -1;
-
- std::string symbol;
- if (data.ticker_valid)
- symbol = data.ticker;
- else if (data.currency_valid)
- symbol = data.currency;
- else
- return -1;
-
- commodity_t * commodity = commodity_t::find_or_create(symbol);
- commodity->add_flags(COMMODITY_STYLE_SUFFIXED | COMMODITY_STYLE_SEPARATED);
-
- if (data.secname_valid)
- commodity->set_name(data.secname);
-
- if (data.memo_valid)
- commodity->set_note(data.memo);
-
- commodities_map::iterator i = ofx_securities.find(data.unique_id);
- if (i == ofx_securities.end()) {
- DEBUG_PRINT("ledger.ofx.parse", "security " << symbol);
- ofx_securities.insert(commodities_pair(data.unique_id, commodity));
- }
-
- // jww (2005-02-09): What is the commodity for data.unitprice?
- if (data.date_unitprice_valid && data.unitprice_valid) {
- DEBUG_PRINT("ledger.ofx.parse", " price " << data.unitprice);
- commodity->add_price(data.date_unitprice, amount_t(data.unitprice));
- }
-
- return 0;
-}
-
-int ofx_proc_status_cb(struct OfxStatusData data, void * status_data)
-{
-}
-
-bool ofx_parser_t::test(std::istream& in) const
-{
- char buf[80];
-
- in.getline(buf, 79);
- if (std::strncmp(buf, "OFXHEADER", 9) == 0) {
- in.clear();
- in.seekg(0, std::ios::beg);
- return true;
- }
- else if (std::strncmp(buf, "<?xml", 5) != 0) {
- in.clear();
- in.seekg(0, std::ios::beg);
- return false;
- }
-
- in.getline(buf, 79);
- if (std::strncmp(buf, "<?OFX", 5) != 0 &&
- std::strncmp(buf, "<?ofx", 5) != 0) {
- in.clear();
- in.seekg(0, std::ios::beg);
- return false;
- }
-
- in.clear();
- in.seekg(0, std::ios::beg);
- return true;
-}
-
-unsigned int ofx_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
-{
- if (! original_file)
- return 0;
-
- curr_journal = journal;
- master_account = master ? master : journal->master;
-
- LibofxContextPtr libofx_context = libofx_get_new_context();
-
- ofx_set_statement_cb (libofx_context, ofx_proc_statement_cb, 0);
- ofx_set_account_cb (libofx_context, ofx_proc_account_cb, 0);
- ofx_set_transaction_cb(libofx_context, ofx_proc_transaction_cb, 0);
- ofx_set_security_cb (libofx_context, ofx_proc_security_cb, 0);
- ofx_set_status_cb (libofx_context, ofx_proc_status_cb, 0);
-
- // The processing is done by way of callbacks, which are all defined
- // above.
- libofx_proc_file(libofx_context, original_file->c_str(), AUTODETECT);
-
- libofx_free_context(libofx_context);
-
- return 1; // jww (2005-02-09): count;
-}
-
-} // namespace ledger
diff --git a/ofx.h b/ofx.h
deleted file mode 100644
index 232daecb..00000000
--- a/ofx.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _OFX_H
-#define _OFX_H
-
-#include "parser.h"
-
-namespace ledger {
-
-class ofx_parser_t : public parser_t
-{
- public:
- virtual bool test(std::istream& in) const;
-
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
-};
-
-} // namespace ledger
-
-#endif // _OFX_H
diff --git a/option.cc b/option.cc
deleted file mode 100644
index 624a8f0b..00000000
--- a/option.cc
+++ /dev/null
@@ -1,1065 +0,0 @@
-#include "option.h"
-#include "config.h"
-#include "report.h"
-#include "debug.h"
-#include "error.h"
-
-#include <iostream>
-#include <cstdarg>
-#include <cstdlib>
-#include <unistd.h>
-
-#include "util.h"
-
-namespace {
- inline void process_option(option_t * opt, const char * arg = NULL) {
- if (! opt->handled) {
- try {
- opt->handler(arg);
- }
- catch (error * err) {
- err->context.push_back
- (new error_context
- (std::string("While parsing option '--") + opt->long_opt +
- "'" + (opt->short_opt != '\0' ?
- (std::string(" (-") + opt->short_opt + "):") : ":")));
- throw err;
- }
- opt->handled = true;
- }
- }
-
- option_t * search_options(option_t * array, const char * name)
- {
- int first = 0;
- int last = CONFIG_OPTIONS_SIZE;
- while (first <= last) {
- int mid = (first + last) / 2; // compute mid point.
-
- int result;
- if ((result = (int)name[0] - (int)array[mid].long_opt[0]) == 0)
- result = std::strcmp(name, array[mid].long_opt);
-
- if (result > 0)
- first = mid + 1; // repeat search in top half.
- else if (result < 0)
- last = mid - 1; // repeat search in bottom half.
- else
- return &array[mid];
- }
- return NULL;
- }
-
- option_t * search_options(option_t * array, const char letter)
- {
- for (int i = 0; i < CONFIG_OPTIONS_SIZE; i++)
- if (letter == array[i].short_opt)
- return &array[i];
- return NULL;
- }
-}
-
-bool process_option(option_t * options, const std::string& name,
- const char * arg)
-{
- option_t * opt = search_options(options, name.c_str());
- if (opt) {
- process_option(opt, arg);
- return true;
- }
- return false;
-}
-
-void process_arguments(option_t * options, int argc, char ** argv,
- const bool anywhere, std::list<std::string>& args)
-{
- int index = 0;
- for (char ** i = argv; *i; i++) {
- if ((*i)[0] != '-') {
- if (anywhere) {
- args.push_back(*i);
- continue;
- } else {
- for (; *i; i++)
- args.push_back(*i);
- break;
- }
- }
-
- // --long-option or -s
- again:
- if ((*i)[1] == '-') {
- if ((*i)[2] == '\0')
- break;
-
- char * name = *i + 2;
- char * value = NULL;
- if (char * p = std::strchr(name, '=')) {
- *p++ = '\0';
- value = p;
- }
-
- option_t * opt = search_options(options, name);
- if (! opt)
- throw new option_error(std::string("illegal option --") + name);
-
- if (opt->wants_arg && value == NULL) {
- value = *++i;
- if (value == NULL)
- throw new option_error(std::string("missing option argument for --") +
- name);
- }
- process_option(opt, value);
- }
- else if ((*i)[1] == '\0') {
- throw new option_error(std::string("illegal option -"));
- }
- else {
- std::list<option_t *> opt_queue;
-
- int x = 1;
- for (char c = (*i)[x]; c != '\0'; x++, c = (*i)[x]) {
- option_t * opt = search_options(options, c);
- if (! opt)
- throw new option_error(std::string("illegal option -") + c);
- opt_queue.push_back(opt);
- }
-
- for (std::list<option_t *>::iterator o = opt_queue.begin();
- o != opt_queue.end(); o++) {
- char * value = NULL;
- if ((*o)->wants_arg) {
- value = *++i;
- if (value == NULL)
- throw new option_error(std::string("missing option argument for -") +
- (*o)->short_opt);
- }
- process_option(*o, value);
- }
- }
-
- next:
- ;
- }
-}
-
-void process_environment(option_t * options, const char ** envp,
- const std::string& tag)
-{
- const char * tag_p = tag.c_str();
- unsigned int tag_len = tag.length();
-
- for (const char ** p = envp; *p; p++)
- if (! tag_p || std::strncmp(*p, tag_p, tag_len) == 0) {
- char buf[128];
- char * r = buf;
- const char * q;
- for (q = *p + tag_len;
- *q && *q != '=' && r - buf < 128;
- q++)
- if (*q == '_')
- *r++ = '-';
- else
- *r++ = std::tolower(*q);
- *r = '\0';
-
- if (*q == '=') {
- try {
- process_option(options, buf, q + 1);
- }
- catch (error * err) {
- err->context.pop_back();
- err->context.push_back
- (new error_context
- (std::string("While parsing environment variable option '") +
- *p + "':"));
- throw err;
- }
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////
-
-namespace ledger {
-
-config_t * config = NULL;
-report_t * report = NULL;
-
-static void show_version(std::ostream& out)
-{
- out << "Ledger " << ledger::version << ", the command-line accounting tool";
- out << "\n\nCopyright (c) 2003-2008, John Wiegley. All rights reserved.\n\n\
-This program is made available under the terms of the BSD Public License.\n\
-See LICENSE file included with the distribution for details and disclaimer.\n";
- out << "\n(modules: gmp, pcre";
-#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
- out << ", xml";
-#endif
-#ifdef HAVE_LIBOFX
- out << ", ofx";
-#endif
- out << ")\n";
-}
-
-void option_full_help(std::ostream& out)
-{
- out << "usage: ledger [options] COMMAND [ACCT REGEX]... [-- [PAYEE REGEX]...]\n\n\
-Basic options:\n\
- -H, --full-help display this help text\n\
- -h, --help display summarized help text\n\
- -v, --version show version information\n\
- -f, --file FILE read ledger data from FILE\n\
- -o, --output FILE write output to FILE\n\
- -i, --init-file FILE initialize ledger using FILE (default: ~/.ledgerrc)\n\
- --cache FILE use FILE as a binary cache when --file is not used\n\
- --no-cache don't use a cache, even if it would be appropriate\n\
- -a, --account NAME use NAME for the default account (useful with QIF)\n\n\
-Report filtering:\n\
- -c, --current show only current and past entries (not future)\n\
- -b, --begin DATE set report begin date\n\
- -e, --end DATE set report end date\n\
- -p, --period STR report using the given period\n\
- --period-sort EXPR sort each report period's entries by EXPR\n\
- -C, --cleared consider only cleared transactions\n\
- -U, --uncleared consider only uncleared transactions\n\
- -R, --real consider only real (non-virtual) transactions\n\
- -L, --actual consider only actual (non-automated) transactions\n\
- -r, --related calculate report using related transactions\n\
- --budget generate budget entries based on periodic entries\n\
- --add-budget show all transactions plus the budget\n\
- --unbudgeted show only unbudgeted transactions\n\
- --forecast EXPR generate forecast entries while EXPR is true\n\
- -l, --limit EXPR calculate only transactions matching EXPR\n\
- -t, --amount EXPR use EXPR to calculate the displayed amount\n\
- -T, --total EXPR use EXPR to calculate the displayed total\n\n\
-Output customization:\n\
- -n, --collapse register: collapse entries; balance: no grand total\n\
- -s, --subtotal balance: show sub-accounts; other: show subtotals\n\
- -P, --by-payee show summarized totals by payee\n\
- -x, --comm-as-payee set commodity name as the payee, for reporting\n\
- -E, --empty balance: show accounts with zero balance\n\
- -W, --weekly show weekly sub-totals\n\
- -M, --monthly show monthly sub-totals\n\
- -Y, --yearly show yearly sub-totals\n\
- --dow show a days-of-the-week report\n\
- -S, --sort EXPR sort report according to the value expression EXPR\n\
- -w, --wide for the default register report, use 132 columns\n\
- --head COUNT show only the first COUNT entries (negative inverts)\n\
- --tail COUNT show only the last COUNT entries (negative inverts)\n\
- --pager PAGER send all output through the given PAGER program\n\
- -A, --average report average transaction amount\n\
- -D, --deviation report deviation from the average\n\
- -%, --percentage report balance totals as a percentile of the parent\n\
- --totals in the \"xml\" report, include running total\n\
- -j, --amount-data print only raw amount data (useful for scripting)\n\
- -J, --total-data print only raw total data\n\
- -d, --display EXPR display only transactions matching EXPR\n\
- -y, --date-format STR use STR as the date format (default: %Y/%m/%d)\n\
- -F, --format STR use STR as the format; for each report type, use:\n\
- --balance-format --register-format --print-format\n\
- --plot-amount-format --plot-total-format --equity-format\n\
- --prices-format --wide-register-format\n\n\
-Commodity reporting:\n\
- --price-db FILE sets the price database to FILE (def: ~/.pricedb)\n\
- -L, --price-exp MINS download quotes only if newer than MINS (def: 1440)\n\
- -Q, --download download price information when needed\n\
- -O, --quantity report commodity totals (this is the default)\n\
- -B, --basis report cost basis of commodities\n\
- -V, --market report last known market value\n\
- -g, --performance report gain/loss for each displayed transaction\n\
- -G, --gain report net gain/loss\n\n\
-Commands:\n\
- balance [REGEXP]... show balance totals for matching accounts\n\
- register [REGEXP]... show register of matching transactions\n\
- print [REGEXP]... print all matching entries\n\
- xml [REGEXP]... print matching entries in XML format\n\
- equity [REGEXP]... output equity entries for matching accounts\n\
- prices [REGEXP]... display price history for matching commodities\n\
- entry DATE PAYEE AMT output a derived entry, based on the arguments\n";
-}
-
-void option_help(std::ostream& out)
-{
- out << "usage: ledger [options] COMMAND [ACCT REGEX]... [-- [PAYEE REGEX]...]\n\n\
-Use -H to see all the help text on one page, or:\n\
- --help-calc calculation options\n\
- --help-disp display options\n\
- --help-comm commodity options\n\n\
-Basic options:\n\
- -h, --help display this help text\n\
- -v, --version show version information\n\
- -f, --file FILE read ledger data from FILE\n\
- -o, --output FILE write output to FILE\n\
- -i, --init-file FILE initialize ledger using FILE (default: ~/.ledgerrc)\n\
- --cache FILE use FILE as a binary cache when --file is not used\n\
- --no-cache don't use a cache, even if it would be appropriate\n\
- -a, --account NAME use NAME for the default account (useful with QIF)\n\n\
-Commands:\n\
- balance [REGEXP]... show balance totals for matching accounts\n\
- register [REGEXP]... show register of matching transactions\n\
- print [REGEXP]... print all matching entries\n\
- xml [REGEXP]... print matching entries in XML format\n\
- equity [REGEXP]... output equity entries for matching accounts\n\
- prices [REGEXP]... display price history for matching commodities\n\
- entry DATE PAYEE AMT output a derived entry, based on the arguments\n";
-}
-
-void option_calc_help(std::ostream& out)
-{
- out << "Options to control how a report is calculated:\n\
- -c, --current show only current and past entries (not future)\n\
- -b, --begin DATE set report begin date\n\
- -e, --end DATE set report end date\n\
- -p, --period STR report using the given period\n\
- --period-sort EXPR sort each report period's entries by EXPR\n\
- -C, --cleared consider only cleared transactions\n\
- -U, --uncleared consider only uncleared transactions\n\
- -R, --real consider only real (non-virtual) transactions\n\
- -L, --actual consider only actual (non-automated) transactions\n\
- -r, --related calculate report using related transactions\n\
- --budget generate budget entries based on periodic entries\n\
- --add-budget show all transactions plus the budget\n\
- --unbudgeted show only unbudgeted transactions\n\
- --forecast EXPR generate forecast entries while EXPR is true\n\
- -l, --limit EXPR calculate only transactions matching EXPR\n\
- -t, --amount EXPR use EXPR to calculate the displayed amount\n\
- -T, --total EXPR use EXPR to calculate the displayed total\n";
-}
-
-void option_disp_help(std::ostream& out)
-{
- out << "Output to control how report results are displayed:\n\
- -n, --collapse register: collapse entries; balance: no grand total\n\
- -s, --subtotal balance: show sub-accounts; other: show subtotals\n\
- -P, --by-payee show summarized totals by payee\n\
- -x, --comm-as-payee set commodity name as the payee, for reporting\n\
- -E, --empty balance: show accounts with zero balance\n\
- -W, --weekly show weekly sub-totals\n\
- -M, --monthly show monthly sub-totals\n\
- -Y, --yearly show yearly sub-totals\n\
- --dow show a days-of-the-week report\n\
- -S, --sort EXPR sort report according to the value expression EXPR\n\
- -w, --wide for the default register report, use 132 columns\n\
- --head COUNT show only the first COUNT entries (negative inverts)\n\
- --tail COUNT show only the last COUNT entries (negative inverts)\n\
- --pager PAGER send all output through the given PAGER program\n\
- -A, --average report average transaction amount\n\
- -D, --deviation report deviation from the average\n\
- -%, --percentage report balance totals as a percentile of the parent\n\
- --totals in the \"xml\" report, include running total\n\
- -j, --amount-data print only raw amount data (useful for scripting)\n\
- -J, --total-data print only raw total data\n\
- -d, --display EXPR display only transactions matching EXPR\n\
- -y, --date-format STR use STR as the date format (default: %Y/%m/%d)\n\
- -F, --format STR use STR as the format; for each report type, use:\n\
- --balance-format --register-format --print-format\n\
- --plot-amount-format --plot-total-format --equity-format\n\
- --prices-format --wide-register-format\n";
-}
-
-void option_comm_help(std::ostream& out)
-{
- out << "Options to control how commodity values are determined:\n\
- --price-db FILE sets the price database to FILE (def: ~/.pricedb)\n\
- -Z, --price-exp MINS download quotes only if newer than MINS (def: 1440)\n\
- -Q, --download download price information when needed\n\
- -O, --quantity report commodity totals (this is the default)\n\
- -B, --basis report cost basis of commodities\n\
- -V, --market report last known market value\n\
- -g, --performance report gain/loss for each displayed transaction\n\
- -G, --gain report net gain/loss\n";
-}
-
-//////////////////////////////////////////////////////////////////////
-//
-// Basic options
-
-OPT_BEGIN(full_help, "H") {
- option_full_help(std::cout);
- throw 0;
-} OPT_END(full_help);
-
-OPT_BEGIN(help, "h") {
- option_help(std::cout);
- throw 0;
-} OPT_END(help);
-
-OPT_BEGIN(help_calc, "") {
- option_calc_help(std::cout);
- throw 0;
-} OPT_END(help_calc);
-
-OPT_BEGIN(help_disp, "") {
- option_disp_help(std::cout);
- throw 0;
-} OPT_END(help_disp);
-
-OPT_BEGIN(help_comm, "") {
- option_comm_help(std::cout);
- throw 0;
-} OPT_END(help_comm);
-
-OPT_BEGIN(version, "v") {
- show_version(std::cout);
- throw 0;
-} OPT_END(version);
-
-OPT_BEGIN(init_file, "i:") {
- std::string path = resolve_path(optarg);
- if (access(path.c_str(), R_OK) != -1)
- config->init_file = path;
- else
- throw new error(std::string("The init file '") + path +
- "' does not exist or is not readable");
-} OPT_END(init_file);
-
-OPT_BEGIN(file, "f:") {
- if (std::string(optarg) == "-") {
- config->data_file = optarg;
- } else {
- std::string path = resolve_path(optarg);
- if (access(path.c_str(), R_OK) != -1)
- config->data_file = path;
- else
- throw new error(std::string("The ledger file '") + path +
- "' does not exist or is not readable");
- }
-} OPT_END(file);
-
-OPT_BEGIN(cache, ":") {
- config->cache_file = resolve_path(optarg);
-} OPT_END(cache);
-
-OPT_BEGIN(no_cache, "") {
- config->cache_file = "<none>";
-} OPT_END(no_cache);
-
-OPT_BEGIN(output, "o:") {
- if (std::string(optarg) != "-") {
- std::string path = resolve_path(optarg);
- report->output_file = path;
- }
-} OPT_END(output);
-
-OPT_BEGIN(account, "a:") {
- config->account = optarg;
-} OPT_END(account);
-
-OPT_BEGIN(debug, ":") {
- config->debug_mode = true;
- ::setenv("DEBUG_CLASS", optarg, 1);
-} OPT_END(debug);
-
-OPT_BEGIN(verbose, "") {
- config->verbose_mode = true;
-} OPT_END(verbose);
-
-OPT_BEGIN(trace, "") {
- config->trace_mode = true;
-} OPT_END(trace);
-
-//////////////////////////////////////////////////////////////////////
-//
-// Report filtering
-
-OPT_BEGIN(effective, "") {
- transaction_t::use_effective_date = true;
-} OPT_END(effective);
-
-OPT_BEGIN(begin, "b:") {
- char buf[128];
- interval_t interval(optarg);
- if (! interval.begin)
- throw new error(std::string("Could not determine beginning of period '") +
- optarg + "'");
-
- if (! report->predicate.empty())
- report->predicate += "&";
- report->predicate += "d>=[";
- report->predicate += interval.begin.to_string();
- report->predicate += "]";
-} OPT_END(begin);
-
-OPT_BEGIN(end, "e:") {
- char buf[128];
- interval_t interval(optarg);
- if (! interval.begin)
- throw new error(std::string("Could not determine end of period '") +
- optarg + "'");
-
- if (! report->predicate.empty())
- report->predicate += "&";
- report->predicate += "d<[";
- report->predicate += interval.begin.to_string();
- report->predicate += "]";
-
- terminus = interval.begin;
-} OPT_END(end);
-
-OPT_BEGIN(current, "c") {
- if (! report->predicate.empty())
- report->predicate += "&";
- report->predicate += "d<=m";
-} OPT_END(current);
-
-OPT_BEGIN(cleared, "C") {
- if (! report->predicate.empty())
- report->predicate += "&";
- report->predicate += "X";
-} OPT_END(cleared);
-
-OPT_BEGIN(uncleared, "U") {
- if (! report->predicate.empty())
- report->predicate += "&";
- report->predicate += "!X";
-} OPT_END(uncleared);
-
-OPT_BEGIN(real, "R") {
- if (! report->predicate.empty())
- report->predicate += "&";
- report->predicate += "R";
-} OPT_END(real);
-
-OPT_BEGIN(actual, "L") {
- if (! report->predicate.empty())
- report->predicate += "&";
- report->predicate += "L";
-} OPT_END(actual);
-
-OPT_BEGIN(lots, "") {
- report->keep_price =
- report->keep_date =
- report->keep_tag = true;
-} OPT_END(lots);
-
-OPT_BEGIN(lot_prices, "") {
- report->keep_price = true;
-} OPT_END(lots_prices);
-
-OPT_BEGIN(lot_dates, "") {
- report->keep_date = true;
-} OPT_END(lots_dates);
-
-OPT_BEGIN(lot_tags, "") {
- report->keep_tag = true;
-} OPT_END(lots_tags);
-
-//////////////////////////////////////////////////////////////////////
-//
-// Output customization
-
-OPT_BEGIN(format, "F:") {
- report->format_string = optarg;
-} OPT_END(format);
-
-OPT_BEGIN(date_format, "y:") {
- report->date_output_format = optarg;
-} OPT_END(date_format);
-
-OPT_BEGIN(input_date_format, ":") {
- config->date_input_format = optarg;
-} OPT_END(input_date_format);
-
-OPT_BEGIN(balance_format, ":") {
- config->balance_format = optarg;
-} OPT_END(balance_format);
-
-OPT_BEGIN(register_format, ":") {
- config->register_format = optarg;
-} OPT_END(register_format);
-
-OPT_BEGIN(wide_register_format, ":") {
- config->wide_register_format = optarg;
-} OPT_END(wide_register_format);
-
-OPT_BEGIN(plot_amount_format, ":") {
- config->plot_amount_format = optarg;
-} OPT_END(plot_amount_format);
-
-OPT_BEGIN(plot_total_format, ":") {
- config->plot_total_format = optarg;
-} OPT_END(plot_total_format);
-
-OPT_BEGIN(print_format, ":") {
- config->print_format = optarg;
-} OPT_END(print_format);
-
-OPT_BEGIN(write_hdr_format, ":") {
- config->write_hdr_format = optarg;
-} OPT_END(write_hdr_format);
-
-OPT_BEGIN(write_xact_format, ":") {
- config->write_xact_format = optarg;
-} OPT_END(write_xact_format);
-
-OPT_BEGIN(equity_format, ":") {
- config->equity_format = optarg;
-} OPT_END(equity_format);
-
-OPT_BEGIN(prices_format, ":") {
- config->prices_format = optarg;
-} OPT_END(prices_format);
-
-OPT_BEGIN(wide, "w") {
- config->register_format = config->wide_register_format;
-} OPT_END(wide);
-
-OPT_BEGIN(head, ":") {
- report->head_entries = std::atoi(optarg);
-} OPT_END(head);
-
-OPT_BEGIN(tail, ":") {
- report->tail_entries = std::atoi(optarg);
-} OPT_END(tail);
-
-OPT_BEGIN(pager, ":") {
- config->pager = optarg;
-} OPT_END(pager);
-
-OPT_BEGIN(truncate, ":") {
- std::string style(optarg);
- if (style == "leading")
- format_t::elision_style = format_t::TRUNCATE_LEADING;
- else if (style == "middle")
- format_t::elision_style = format_t::TRUNCATE_MIDDLE;
- else if (style == "trailing")
- format_t::elision_style = format_t::TRUNCATE_TRAILING;
- else if (style == "abbrev")
- format_t::elision_style = format_t::ABBREVIATE;
-} OPT_END(truncate);
-
-OPT_BEGIN(abbrev_len, ":") {
- format_t::abbrev_length = std::atoi(optarg);
-} OPT_END(abbrev_len);
-
-OPT_BEGIN(empty, "E") {
- report->show_empty = true;
-} OPT_END(empty);
-
-OPT_BEGIN(collapse, "n") {
- report->show_collapsed = true;
-} OPT_END(collapse);
-
-OPT_BEGIN(subtotal, "s") {
- report->show_subtotal = true;
-} OPT_END(subtotal);
-
-OPT_BEGIN(totals, "") {
- report->show_totals = true;
-} OPT_END(totals);
-
-OPT_BEGIN(sort, "S:") {
- report->sort_string = optarg;
-} OPT_END(sort);
-
-OPT_BEGIN(sort_entries, "") {
- report->sort_string = optarg;
- report->entry_sort = true;
-} OPT_END(sort_entries);
-
-OPT_BEGIN(sort_all, "") {
- report->sort_string = optarg;
- report->entry_sort = false;
- report->sort_all = true;
-} OPT_END(sort_all);
-
-OPT_BEGIN(period_sort, ":") {
- report->sort_string = optarg;
- report->entry_sort = true;
-} OPT_END(period_sort);
-
-OPT_BEGIN(related, "r") {
- report->show_related = true;
-} OPT_END(related);
-
-OPT_BEGIN(descend, "") {
- std::string arg(optarg);
- std::string::size_type beg = 0;
- report->descend_expr = "";
- for (std::string::size_type pos = arg.find(';');
- pos != std::string::npos;
- beg = pos + 1, pos = arg.find(';', beg))
- report->descend_expr += (std::string("t=={") +
- std::string(arg, beg, pos - beg) + "};");
- report->descend_expr += (std::string("t=={") +
- std::string(arg, beg) + "}");
-} OPT_END(descend);
-
-OPT_BEGIN(descend_if, "") {
- report->descend_expr = optarg;
-} OPT_END(descend_if);
-
-OPT_BEGIN(period, "p:") {
- if (report->report_period.empty()) {
- report->report_period = optarg;
- } else {
- report->report_period += " ";
- report->report_period += optarg;
- }
-
- // If the period gives a beginning and/or ending date, make sure to
- // modify the calculation predicate (via the --begin and --end
- // options) to take this into account.
-
- interval_t interval(report->report_period);
-
- if (interval.begin) {
- if (! report->predicate.empty())
- report->predicate += "&";
- report->predicate += "d>=[";
- report->predicate += interval.begin.to_string();
- report->predicate += "]";
- }
-
- if (interval.end) {
- if (! report->predicate.empty())
- report->predicate += "&";
- report->predicate += "d<[";
- report->predicate += interval.end.to_string();
- report->predicate += "]";
-
- terminus = interval.end;
- }
-} OPT_END(period);
-
-OPT_BEGIN(daily, "") {
- if (report->report_period.empty())
- report->report_period = "daily";
- else
- report->report_period = std::string("daily ") + report->report_period;
-} OPT_END(daily);
-
-OPT_BEGIN(weekly, "W") {
- if (report->report_period.empty())
- report->report_period = "weekly";
- else
- report->report_period = std::string("weekly ") + report->report_period;
-} OPT_END(weekly);
-
-OPT_BEGIN(monthly, "M") {
- if (report->report_period.empty())
- report->report_period = "monthly";
- else
- report->report_period = std::string("monthly ") + report->report_period;
-} OPT_END(monthly);
-
-OPT_BEGIN(quarterly, "") {
- if (report->report_period.empty())
- report->report_period = "quarterly";
- else
- report->report_period = std::string("quarterly ") + report->report_period;
-} OPT_END(quarterly);
-
-OPT_BEGIN(yearly, "Y") {
- if (report->report_period.empty())
- report->report_period = "yearly";
- else
- report->report_period = std::string("yearly ") + report->report_period;
-} OPT_END(yearly);
-
-OPT_BEGIN(dow, "") {
- report->days_of_the_week = true;
-} OPT_END(dow);
-
-OPT_BEGIN(by_payee, "P") {
- report->by_payee = true;
-} OPT_END(by_payee);
-
-OPT_BEGIN(comm_as_payee, "x") {
- report->comm_as_payee = true;
-} OPT_END(comm_as_payee);
-
-OPT_BEGIN(code_as_payee, "") {
- report->code_as_payee = true;
-} OPT_END(code_as_payee);
-
-OPT_BEGIN(budget, "") {
- report->budget_flags = BUDGET_BUDGETED;
-} OPT_END(budget);
-
-OPT_BEGIN(add_budget, "") {
- report->budget_flags = BUDGET_BUDGETED | BUDGET_UNBUDGETED;
-} OPT_END(add_budget);
-
-OPT_BEGIN(unbudgeted, "") {
- report->budget_flags = BUDGET_UNBUDGETED;
-} OPT_END(unbudgeted);
-
-OPT_BEGIN(forecast, ":") {
- report->forecast_limit = optarg;
-} OPT_END(forecast);
-
-OPT_BEGIN(reconcile, ":") {
- report->reconcile_balance = optarg;
-} OPT_END(reconcile);
-
-OPT_BEGIN(reconcile_date, ":") {
- report->reconcile_date = optarg;
-} OPT_END(reconcile_date);
-
-OPT_BEGIN(limit, "l:") {
- if (! report->predicate.empty())
- report->predicate += "&";
- report->predicate += "(";
- report->predicate += optarg;
- report->predicate += ")";
-} OPT_END(limit);
-
-OPT_BEGIN(only, ":") {
- if (! report->secondary_predicate.empty())
- report->secondary_predicate += "&";
- report->secondary_predicate += "(";
- report->secondary_predicate += optarg;
- report->secondary_predicate += ")";
-} OPT_END(only);
-
-OPT_BEGIN(display, "d:") {
- if (! report->display_predicate.empty())
- report->display_predicate += "&";
- report->display_predicate += "(";
- report->display_predicate += optarg;
- report->display_predicate += ")";
-} OPT_END(display);
-
-OPT_BEGIN(amount, "t:") {
- ledger::amount_expr = optarg;
-} OPT_END(amount);
-
-OPT_BEGIN(total, "T:") {
- ledger::total_expr = optarg;
-} OPT_END(total);
-
-OPT_BEGIN(amount_data, "j") {
- report->format_string = config->plot_amount_format;
-} OPT_END(amount_data);
-
-OPT_BEGIN(total_data, "J") {
- report->format_string = config->plot_total_format;
-} OPT_END(total_data);
-
-OPT_BEGIN(ansi, "") {
- format_t::ansi_codes = true;
- format_t::ansi_invert = false;
-} OPT_END(ansi);
-
-OPT_BEGIN(ansi_invert, "") {
- format_t::ansi_codes =
- format_t::ansi_invert = true;
-} OPT_END(ansi);
-
-//////////////////////////////////////////////////////////////////////
-//
-// Commodity reporting
-
-OPT_BEGIN(base, ":") {
- amount_t::keep_base = true;
-} OPT_END(base);
-
-OPT_BEGIN(price_db, ":") {
- config->price_db = optarg;
-} OPT_END(price_db);
-
-OPT_BEGIN(price_exp, "Z:") {
- config->pricing_leeway = std::atol(optarg) * 60;
-} OPT_END(price_exp);
-
-OPT_BEGIN(download, "Q") {
- config->download_quotes = true;
-} OPT_END(download);
-
-OPT_BEGIN(quantity, "O") {
- ledger::amount_expr = "@a";
- ledger::total_expr = "@O";
-} OPT_END(quantity);
-
-OPT_BEGIN(basis, "B") {
- ledger::amount_expr = "@b";
- ledger::total_expr = "@B";
-} OPT_END(basis);
-
-OPT_BEGIN(price, "I") {
- ledger::amount_expr = "@i";
- ledger::total_expr = "@I";
-} OPT_END(price);
-
-OPT_BEGIN(market, "V") {
- report->show_revalued = true;
-
- ledger::amount_expr = "@v";
- ledger::total_expr = "@V";
-} OPT_END(market);
-
-namespace {
- void parse_price_setting(const char * optarg)
- {
- char * equals = std::strchr(optarg, '=');
- if (! equals)
- return;
-
- while (std::isspace(*optarg))
- optarg++;
- while (equals > optarg && std::isspace(*(equals - 1)))
- equals--;
-
- std::string symbol(optarg, 0, equals - optarg);
- amount_t price(equals + 1);
-
- if (commodity_t * commodity = commodity_t::find_or_create(symbol)) {
- commodity->add_price(datetime_t::now, price);
- commodity->history()->bogus_time = datetime_t::now;
- }
- }
-}
-
-OPT_BEGIN(set_price, ":") {
- std::string arg(optarg);
- std::string::size_type beg = 0;
- for (std::string::size_type pos = arg.find(';');
- pos != std::string::npos;
- beg = pos + 1, pos = arg.find(';', beg))
- parse_price_setting(std::string(arg, beg, pos - beg).c_str());
- parse_price_setting(std::string(arg, beg).c_str());
-} OPT_END(set_price);
-
-OPT_BEGIN(performance, "g") {
- ledger::amount_expr = "@P(@a,@m)-@b";
- ledger::total_expr = "@P(@O,@m)-@B";
-} OPT_END(performance);
-
-OPT_BEGIN(gain, "G") {
- report->show_revalued =
- report->show_revalued_only = true;
-
- ledger::amount_expr = "@a";
- ledger::total_expr = "@G";
-} OPT_END(gain);
-
-static std::string expand_value_expr(const std::string& tmpl,
- const std::string& expr)
-{
- std::string xp = tmpl;
- for (std::string::size_type i = xp.find('#');
- i != std::string::npos;
- i = xp.find('#'))
- xp = (std::string(xp, 0, i) + "(" + expr + ")" +
- std::string(xp, i + 1));
- return xp;
-}
-
-OPT_BEGIN(average, "A") {
- ledger::total_expr = expand_value_expr("@A(#)", ledger::total_expr.expr);
-} OPT_END(average);
-
-OPT_BEGIN(deviation, "D") {
- ledger::total_expr = expand_value_expr("@t-@A(#)", ledger::total_expr.expr);
-} OPT_END(deviation);
-
-OPT_BEGIN(percentage, "%") {
- ledger::total_expr = expand_value_expr("^#&{100.0%}*(#/^#)",
- ledger::total_expr.expr);
-} OPT_END(percentage);
-
-//////////////////////////////////////////////////////////////////////
-
-option_t config_options[CONFIG_OPTIONS_SIZE] = {
- { "abbrev-len", '\0', true, opt_abbrev_len, false },
- { "account", 'a', true, opt_account, false },
- { "actual", 'L', false, opt_actual, false },
- { "add-budget", '\0', false, opt_add_budget, false },
- { "amount", 't', true, opt_amount, false },
- { "amount-data", 'j', false, opt_amount_data, false },
- { "ansi", '\0', false, opt_ansi, false },
- { "ansi-invert", '\0', false, opt_ansi_invert, false },
- { "average", 'A', false, opt_average, false },
- { "balance-format", '\0', true, opt_balance_format, false },
- { "base", '\0', false, opt_base, false },
- { "basis", 'B', false, opt_basis, false },
- { "begin", 'b', true, opt_begin, false },
- { "budget", '\0', false, opt_budget, false },
- { "by-payee", 'P', false, opt_by_payee, false },
- { "cache", '\0', true, opt_cache, false },
- { "cleared", 'C', false, opt_cleared, false },
- { "code-as-payee", '\0', false, opt_code_as_payee, false },
- { "collapse", 'n', false, opt_collapse, false },
- { "comm-as-payee", 'x', false, opt_comm_as_payee, false },
- { "cost", '\0', false, opt_basis, false },
- { "current", 'c', false, opt_current, false },
- { "daily", '\0', false, opt_daily, false },
- { "date-format", 'y', true, opt_date_format, false },
- { "debug", '\0', true, opt_debug, false },
- { "descend", '\0', true, opt_descend, false },
- { "descend-if", '\0', true, opt_descend_if, false },
- { "deviation", 'D', false, opt_deviation, false },
- { "display", 'd', true, opt_display, false },
- { "dow", '\0', false, opt_dow, false },
- { "download", 'Q', false, opt_download, false },
- { "effective", '\0', false, opt_effective, false },
- { "empty", 'E', false, opt_empty, false },
- { "end", 'e', true, opt_end, false },
- { "equity-format", '\0', true, opt_equity_format, false },
- { "file", 'f', true, opt_file, false },
- { "forecast", '\0', true, opt_forecast, false },
- { "format", 'F', true, opt_format, false },
- { "full-help", 'H', false, opt_full_help, false },
- { "gain", 'G', false, opt_gain, false },
- { "head", '\0', true, opt_head, false },
- { "help", 'h', false, opt_help, false },
- { "help-calc", '\0', false, opt_help_calc, false },
- { "help-comm", '\0', false, opt_help_comm, false },
- { "help-disp", '\0', false, opt_help_disp, false },
- { "init-file", 'i', true, opt_init_file, false },
- { "input-date-format", '\0', true, opt_input_date_format, false },
- { "limit", 'l', true, opt_limit, false },
- { "lot-dates", '\0', false, opt_lot_dates, false },
- { "lot-prices", '\0', false, opt_lot_prices, false },
- { "lot-tags", '\0', false, opt_lot_tags, false },
- { "lots", '\0', false, opt_lots, false },
- { "market", 'V', false, opt_market, false },
- { "monthly", 'M', false, opt_monthly, false },
- { "no-cache", '\0', false, opt_no_cache, false },
- { "only", '\0', true, opt_only, false },
- { "output", 'o', true, opt_output, false },
- { "pager", '\0', true, opt_pager, false },
- { "percentage", '%', false, opt_percentage, false },
- { "performance", 'g', false, opt_performance, false },
- { "period", 'p', true, opt_period, false },
- { "period-sort", '\0', true, opt_period_sort, false },
- { "plot-amount-format", '\0', true, opt_plot_amount_format, false },
- { "plot-total-format", '\0', true, opt_plot_total_format, false },
- { "price", 'I', false, opt_price, false },
- { "price-db", '\0', true, opt_price_db, false },
- { "price-exp", 'Z', true, opt_price_exp, false },
- { "prices-format", '\0', true, opt_prices_format, false },
- { "print-format", '\0', true, opt_print_format, false },
- { "quantity", 'O', false, opt_quantity, false },
- { "quarterly", '\0', false, opt_quarterly, false },
- { "real", 'R', false, opt_real, false },
- { "reconcile", '\0', true, opt_reconcile, false },
- { "reconcile-date", '\0', true, opt_reconcile_date, false },
- { "register-format", '\0', true, opt_register_format, false },
- { "related", 'r', false, opt_related, false },
- { "set-price", '\0', true, opt_set_price, false },
- { "sort", 'S', true, opt_sort, false },
- { "sort-all", '\0', true, opt_sort_all, false },
- { "sort-entries", '\0', true, opt_sort_entries, false },
- { "subtotal", 's', false, opt_subtotal, false },
- { "tail", '\0', true, opt_tail, false },
- { "total", 'T', true, opt_total, false },
- { "total-data", 'J', false, opt_total_data, false },
- { "totals", '\0', false, opt_totals, false },
- { "trace", '\0', false, opt_trace, false },
- { "truncate", '\0', true, opt_truncate, false },
- { "unbudgeted", '\0', false, opt_unbudgeted, false },
- { "uncleared", 'U', false, opt_uncleared, false },
- { "verbose", '\0', false, opt_verbose, false },
- { "version", 'v', false, opt_version, false },
- { "weekly", 'W', false, opt_weekly, false },
- { "wide", 'w', false, opt_wide, false },
- { "wide-register-format", '\0', true, opt_wide_register_format, false },
- { "write-hdr-format", '\0', true, opt_write_hdr_format, false },
- { "write-xact-format", '\0', true, opt_write_xact_format, false },
- { "yearly", 'Y', false, opt_yearly, false },
-};
-
-} // namespace ledger
diff --git a/option.h b/option.h
deleted file mode 100644
index 91838b99..00000000
--- a/option.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef _OPTION_H
-#define _OPTION_H
-
-#include <list>
-#include <string>
-#include <exception>
-
-#include "error.h"
-
-typedef void (*handler_t)(const char * arg);
-
-struct option_t {
- const char * long_opt;
- char short_opt;
- bool wants_arg;
- handler_t handler;
- bool handled;
-};
-
-class option_error : public error {
- public:
- option_error(const std::string& reason) throw() : error(reason) {}
- virtual ~option_error() throw() {}
-};
-
-bool process_option(option_t * options, const std::string& opt,
- const char * arg = NULL);
-void process_arguments(option_t * options, int argc, char ** argv,
- const bool anywhere, std::list<std::string>& args);
-void process_environment(option_t * options, const char ** envp,
- const std::string& tag);
-
-namespace ledger {
-
-class config_t;
-class report_t;
-
-extern config_t * config;
-extern report_t * report;
-
-#define CONFIG_OPTIONS_SIZE 97
-extern option_t config_options[CONFIG_OPTIONS_SIZE];
-
-void option_help(std::ostream& out);
-
-#define OPT_BEGIN(tag, chars) \
- void opt_ ## tag(const char * optarg)
-
-#define OPT_END(tag)
-
-} // namespace ledger
-
-#endif // _OPTION_H
diff --git a/parser.cc b/parser.cc
deleted file mode 100644
index debe5558..00000000
--- a/parser.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-#include "parser.h"
-#include "journal.h"
-#include "config.h"
-
-#include <fstream>
-#ifdef WIN32
-#include <io.h>
-#else
-#include <unistd.h>
-#endif
-
-namespace ledger {
-
-typedef std::list<parser_t *> parsers_list;
-
-static parsers_list * parsers = NULL;
-
-void initialize_parser_support()
-{
- parsers = new parsers_list;
-}
-
-void shutdown_parser_support()
-{
- if (parsers) {
- delete parsers;
- parsers = NULL;
- }
-}
-
-bool register_parser(parser_t * parser)
-{
- parsers_list::iterator i;
- for (i = parsers->begin(); i != parsers->end(); i++)
- if (*i == parser)
- break;
- if (i != parsers->end())
- return false;
-
- parsers->push_back(parser);
-
- return true;
-}
-
-bool unregister_parser(parser_t * parser)
-{
- parsers_list::iterator i;
- for (i = parsers->begin(); i != parsers->end(); i++)
- if (*i == parser)
- break;
- if (i == parsers->end())
- return false;
-
- parsers->erase(i);
-
- return true;
-}
-
-unsigned int parse_journal(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
-{
- if (! master)
- master = journal->master;
-
- for (parsers_list::iterator i = parsers->begin();
- i != parsers->end();
- i++)
- if ((*i)->test(in))
- return (*i)->parse(in, config, journal, master, original_file);
-
- return 0;
-}
-
-unsigned int parse_journal_file(const std::string& path,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
-{
- journal->sources.push_back(path);
-
- if (access(path.c_str(), R_OK) == -1)
- throw new error(std::string("Cannot read file '") + path + "'");
-
- if (! original_file)
- original_file = &path;
-
- std::ifstream stream(path.c_str());
- return parse_journal(stream, config, journal, master, original_file);
-}
-
-extern parser_t * binary_parser_ptr;
-extern parser_t * xml_parser_ptr;
-extern parser_t * textual_parser_ptr;
-
-unsigned int parse_ledger_data(config_t& config,
- journal_t * journal,
- parser_t * cache_parser,
- parser_t * xml_parser,
- parser_t * stdin_parser)
-{
- unsigned int entry_count = 0;
-
- if (! cache_parser)
- cache_parser = binary_parser_ptr;
- if (! xml_parser)
- xml_parser = xml_parser_ptr;
- if (! stdin_parser)
- stdin_parser = textual_parser_ptr;
-
- DEBUG_PRINT("ledger.config.cache",
- "3. use_cache = " << config.use_cache);
-
- if (! config.init_file.empty() &&
- access(config.init_file.c_str(), R_OK) != -1) {
- if (parse_journal_file(config.init_file, config, journal) ||
- journal->auto_entries.size() > 0 ||
- journal->period_entries.size() > 0)
- throw new error(std::string("Entries found in initialization file '") +
- config.init_file + "'");
-
- journal->sources.pop_front(); // remove init file
- }
-
- if (config.use_cache && ! config.cache_file.empty() &&
- ! config.data_file.empty()) {
- DEBUG_PRINT("ledger.config.cache",
- "using_cache " << config.cache_file);
- config.cache_dirty = true;
- if (access(config.cache_file.c_str(), R_OK) != -1) {
- std::ifstream stream(config.cache_file.c_str());
- if (cache_parser && cache_parser->test(stream)) {
- std::string price_db_orig = journal->price_db;
- journal->price_db = config.price_db;
- entry_count += cache_parser->parse(stream, config, journal,
- NULL, &config.data_file);
- if (entry_count > 0)
- config.cache_dirty = false;
- else
- journal->price_db = price_db_orig;
- }
- }
- }
-
- if (entry_count == 0 && ! config.data_file.empty()) {
- account_t * acct = NULL;
- if (! config.account.empty())
- acct = journal->find_account(config.account);
-
- journal->price_db = config.price_db;
- if (! journal->price_db.empty() &&
- access(journal->price_db.c_str(), R_OK) != -1) {
- if (parse_journal_file(journal->price_db, config, journal)) {
- throw new error("Entries not allowed in price history file");
- } else {
- DEBUG_PRINT("ledger.config.cache",
- "read price database " << journal->price_db);
- journal->sources.pop_back();
- }
- }
-
- DEBUG_PRINT("ledger.config.cache",
- "rejected cache, parsing " << config.data_file);
- if (config.data_file == "-") {
- config.use_cache = false;
- journal->sources.push_back("<stdin>");
-#if 0
- // jww (2006-03-23): Why doesn't XML work on stdin?
- if (xml_parser && std::cin.peek() == '<')
- entry_count += xml_parser->parse(std::cin, config, journal,
- acct);
- else if (stdin_parser)
-#endif
- entry_count += stdin_parser->parse(std::cin, config,
- journal, acct);
- }
- else if (access(config.data_file.c_str(), R_OK) != -1) {
- entry_count += parse_journal_file(config.data_file, config,
- journal, acct);
- if (! journal->price_db.empty())
- journal->sources.push_back(journal->price_db);
- }
- // Clear out what was set during the textual parsing phase
- clear_account_xdata acct_cleaner;
- walk_accounts(*journal->master, acct_cleaner);
- }
-
- VALIDATE(journal->valid());
-
- return entry_count;
-}
-
-} // namespace ledger
diff --git a/parser.h b/parser.h
deleted file mode 100644
index 6178d293..00000000
--- a/parser.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef _PARSER_H
-#define _PARSER_H
-
-#include <iostream>
-#include <string>
-
-#include "error.h"
-
-namespace ledger {
-
-class account_t;
-class journal_t;
-class config_t;
-
-class parser_t
-{
- public:
- virtual ~parser_t() {}
-
- virtual bool test(std::istream& in) const = 0;
-
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL) = 0;
-};
-
-bool register_parser(parser_t * parser);
-bool unregister_parser(parser_t * parser);
-
-unsigned int parse_journal(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
-
-unsigned int parse_journal_file(const std::string& path,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
-
-unsigned int parse_ledger_data(config_t& config,
- journal_t * journal,
- parser_t * cache_parser = NULL,
- parser_t * xml_parser = NULL,
- parser_t * stdin_parser = NULL);
-
-void initialize_parser_support();
-void shutdown_parser_support();
-
-class parse_error : public error {
- public:
- parse_error(const std::string& reason, error_context * ctxt = NULL) throw()
- : error(reason, ctxt) {}
- virtual ~parse_error() throw() {}
-};
-
-} // namespace ledger
-
-#endif // _PARSER_H
diff --git a/python/__init__.py b/python/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/python/__init__.py
diff --git a/python/demo.py b/python/demo.py
new file mode 100755
index 00000000..7b4003f3
--- /dev/null
+++ b/python/demo.py
@@ -0,0 +1,293 @@
+#!/usr/bin/env python
+
+import sys
+from datetime import datetime
+
+# The following literate program will demonstrate, by example, how to use the
+# Ledger Python module to access your data and build custom reports using the
+# magic of Python.
+
+import ledger
+
+print "Welcome to the Ledger.Python demo!"
+
+# Some quick helper functions to help us assert various types of truth
+# throughout the script.
+
+def assertEqual(pat, candidate):
+ if pat != candidate:
+ raise Exception("FAILED: %s != %s" % (pat, candidate))
+ sys.exit(1)
+
+###############################################################################
+#
+# COMMODITIES
+#
+# Every amount in Ledger has a commodity, even if it is the "null commodity".
+# What's special about commodities are not just their symbol, but how they
+# alter the way amounts are displayed.
+#
+# For example, internally Ledger uses infinite precision rational numbers,
+# which have no decimal point. So how does it know that $1.00 / $0.75 should
+# be displayed as $1.33, and not with an infinitely repeating decimal? It
+# does it by consulting the commodity.
+#
+# Whenever an amount is encountered in your data file, Ledger observes how you
+# specified it:
+# - How many digits of precision did you use?
+# - Was the commodity name before or after the amount?
+# - Was the commodity separated from the amount by a space?
+# - Did you use thousands markers (1,000)?
+# - Did you use European-style numbers (1.000,00)?
+#
+# By tracking this information for each commodity, Ledger knows how you want
+# to see the amount in your reports. This way, dollars can be output as
+# $123.56, while stock options could be output as 10.113 AAPL.
+#
+# Your program can access the known set of commodities using the global
+# `ledger.commodities'. This object behaves like a dict, and support all of
+# the non-modifying dict protocol methods. If you wish to create a new
+# commodity without parsing an amount, you can use the method
+# `find_or_create':
+
+comms = ledger.commodities
+
+usd = comms.find_or_create('$')
+eur = comms.find_or_create('EUR')
+xcd = comms.find_or_create('XCD')
+
+assert not comms.find('CAD')
+assert not comms.has_key('CAD')
+assert not 'CAD' in comms
+
+# The above mentioned commodity display attributes can be set using commodity
+# display flags. This is not something you will usually be doing, however, as
+# these flags can be inferred correctly from a large enough set of sample
+# amounts, such as those found in your data file. If you live in Europe and
+# want all amounts to default to the European-style, set the static variable
+# `european_by_default'.
+
+eur.add_flags(ledger.COMMODITY_STYLE_EUROPEAN)
+assert eur.has_flags(ledger.COMMODITY_STYLE_EUROPEAN)
+assert not eur.has_flags(ledger.COMMODITY_STYLE_THOUSANDS)
+
+comms.european_by_default = True
+
+# There are a few built-in commodities: null, %, h, m and s. Normally you
+# don't need to worry about them, but they'll show up if you examine all the
+# keys in the commodities dict.
+
+assertEqual([u'', u'$', u'%', u'EUR', u'XCD', u'h', u'm', u's'],
+ sorted(comms.keys()))
+
+# All the styles of dict iteration are supported:
+
+for symbol in comms.iterkeys():
+ pass
+for commodity in comms.itervalues():
+ pass
+#for symbol, commodity in comms.iteritems():
+# pass
+#for symbol, commodity in comms:
+# pass
+
+# Another important thing about commodities is that they remember if they've
+# been exchanged for another commodity, and what the conversion rate was on
+# that date. You can record specific conversion rates for any date using the
+# `exchange' method.
+
+comms.exchange(eur, ledger.Amount('$0.77')) # Trade 1 EUR for $0.77
+comms.exchange(eur, ledger.Amount('$0.66'), datetime.now())
+
+# For the most part, however, you won't be interacting with commodities
+# directly, except maybe to look at their `symbol'.
+
+assertEqual('$', usd.symbol)
+assertEqual('$', comms['$'].symbol)
+
+###############################################################################
+#
+# AMOUNTS & BALANCES
+#
+# Ledger deals with two basic numerical values: Amount and Balance objects.
+# An Amount is an infinite-precision rational with an associated commodity
+# (even if it is the null commodity, which is called an "uncommoditized
+# amount"). A Balance is a collection of Amounts of differing commodities.
+#
+# Amounts support all the math operations you might expect of an integer,
+# except it carries a commodity. Let's take dollars for example:
+
+zero = ledger.Amount("$0")
+one = ledger.Amount("$1")
+oneb = ledger.Amount("$1")
+two = ledger.Amount("$2")
+three = ledger.Amount("3") # uncommoditized
+
+assert one == oneb # numeric equality, not identity
+assert one != two
+assert not zero # tests if it would *display* as a zero
+assert one < two
+assert one > zero
+
+# For addition and subtraction, only amounts of the same commodity may be
+# used, unless one of the amounts has no commodity at all -- in which case the
+# result uses the commodity of the other value. Adding $10 to 10 EUR, for
+# example, causes an ArithmeticError exception, but adding 10 to $10 gives
+# $20.
+
+four = ledger.Amount(two) # make a copy
+four += two
+assertEqual(four, two + two)
+assertEqual(zero, one - one)
+
+try:
+ two += ledger.Amount("20 EUR")
+ assert False
+except ArithmeticError:
+ pass
+
+# Use `number' to get the uncommoditized version of an Amount
+
+assertEqual(three, (two + one).number())
+
+# Multiplication and division does supports Amounts of different commodities,
+# however:
+# - If either amount is uncommoditized, the result carries the commodity of
+# the other amount.
+# - Otherwise, the result always carries the commodity of the first amount.
+
+five = ledger.Amount("5 CAD")
+
+assertEqual(one, two / two)
+assertEqual(five, (five * ledger.Amount("$2")) - ledger.Amount("5"))
+
+# An amount's commodity determines the decimal precision it's displayed with.
+# However, this "precision" is a notional thing only. You can tell an amount
+# to ignore its display precision by setting `keep_precision' to True.
+# (Uncommoditized amounts ignore the value of `keep_precision', and assume it
+# is always True). In this case, Ledger does its best to maintain maximal
+# precision by watching how the Amount is used. That is, 1.01 * 1.01 yields a
+# precision of 4. This tracking is just a best estimate, however, since
+# internally Ledger never uses floating-point values.
+
+amt = ledger.Amount('$100.12')
+mini = ledger.Amount('0.00045')
+
+assert not amt.keep_precision
+
+assertEqual(5, mini.precision)
+assertEqual(5, mini.display_precision) # display_precision == precision
+assertEqual(2, amt.precision)
+assertEqual(2, amt.display_precision)
+
+mini *= mini
+amt *= amt
+
+assertEqual(10, mini.precision)
+assertEqual(10, mini.display_precision)
+assertEqual(4, amt.precision)
+assertEqual(2, amt.display_precision)
+
+# There are several other supported math operations:
+
+amt = ledger.Amount('$100.12')
+market = ((ledger.Amount('1 EUR') / ledger.Amount('$0.77')) * amt)
+
+assertEqual(market, amt.value(eur)) # find present market value
+
+assertEqual('$-100.12', str(amt.negated())) # negate the amount
+assertEqual('$-100.12', str(- amt)) # negate it more simply
+assertEqual('$0.01', str(amt.inverted())) # reverse NUM/DEM
+assertEqual('$100.12', str(amt.rounded())) # round it to display precision
+assertEqual('$100.12', str(amt.truncated())) # truncate to display precision
+assertEqual('$100.00', str(amt.floored())) # floor it to nearest integral
+assertEqual('$100.12', str(abs(amt))) # absolute value
+assertEqual('$100.12', str(amt)) # render to a string
+assertEqual('100.12', amt.quantity_string()) # render quantity to a string
+assertEqual('100.12', str(amt.number())) # strip away commodity
+assertEqual(1, amt.sign()) # -1, 0 or 1
+assert amt.is_nonzero() # True if display amount nonzero
+assert not amt.is_zero() # True if display amount is zero
+assert not amt.is_realzero() # True only if value is 0/0
+assert not amt.is_null() # True if uninitialized
+
+# Amounts can also be converted the standard floats and integers, although
+# this is not recommend since it can lose precision.
+
+assertEqual(100.12, amt.to_double())
+assert amt.fits_in_long() # there is no `fits_in_double'
+assertEqual(100, amt.to_long())
+
+# Finally, amounts can be annotated to provide additional information about
+# "lots" of a given commodity. This example shows $100.12 that was purchased
+# on 2009/10/01 for 140 EUR. Lot information can be accessed through via the
+# Amount's `annotation' property. You can also strip away lot details to get
+# the underlying amount. If you want the total price of any Amount, by
+# multiplying by its per-unit lot price, call the `Amount.price' method
+# instead of the `Annotation.price' property.
+
+amt2 = ledger.Amount('$100.12 {140 EUR} [2009/10/01]')
+
+assert amt2.has_annotation()
+assertEqual(amt, amt2.strip_annotations())
+
+assertEqual(ledger.Amount('140 EUR'), amt2.annotation.price)
+assertEqual(ledger.Amount('14016,8 EUR'), amt2.price()) # european amount!
+
+###############################################################################
+#
+# VALUES
+#
+# As common as Amounts and Balances are, there is a more prevalent numeric
+# type you will encounter when generating reports: Value objects. A Value is
+# a variadic type that can be any of the following types:
+# - Amount
+# - Balance
+# - boolean
+# - integer
+# - datetime
+# - date
+# - string
+# - regex
+# - sequence
+#
+# The reason for the variadic type is that it supports dynamic self-promotion.
+# For example, it is illegal to add two Amounts of different commodities, but
+# it is not illegal to add two Value amounts of different commodities. In the
+# former case an exception in raised, but in the latter the Value simply
+# promotes itself to a Balance object to make the addition valid.
+#
+# Values are not used by any of Ledger's data objects (Journal, Transaction,
+# Posting or Account), but they are used extensively by value expressions.
+
+val = ledger.Value('$100.00')
+
+assert val.is_amount()
+assertEqual('$', val.to_amount().commodity.symbol)
+
+# JOURNALS
+
+#journal.find_account('')
+#journal.find_or_create_account('')
+
+# ACCOUNTS
+
+#account.name
+#account.fullname()
+#account.amount
+#account.total
+
+# TRANSACTIONS
+
+#txn.payee
+
+# POSTINGS
+
+#post.account
+
+# REPORTING
+
+#journal.collect('-M food')
+#journal.collect_accounts('^assets ^liab ^equity')
+
+print 'Demo completed successfully.'
diff --git a/python/res/asc.gif b/python/res/asc.gif
new file mode 100644
index 00000000..74157867
--- /dev/null
+++ b/python/res/asc.gif
Binary files differ
diff --git a/python/res/bg.gif b/python/res/bg.gif
new file mode 100644
index 00000000..fac668fc
--- /dev/null
+++ b/python/res/bg.gif
Binary files differ
diff --git a/python/res/desc.gif b/python/res/desc.gif
new file mode 100644
index 00000000..3b30b3c5
--- /dev/null
+++ b/python/res/desc.gif
Binary files differ
diff --git a/python/res/icons/first.png b/python/res/icons/first.png
new file mode 100644
index 00000000..6f11fcb0
--- /dev/null
+++ b/python/res/icons/first.png
Binary files differ
diff --git a/python/res/icons/last.png b/python/res/icons/last.png
new file mode 100644
index 00000000..72079357
--- /dev/null
+++ b/python/res/icons/last.png
Binary files differ
diff --git a/python/res/icons/next.png b/python/res/icons/next.png
new file mode 100644
index 00000000..4a2f9d4e
--- /dev/null
+++ b/python/res/icons/next.png
Binary files differ
diff --git a/python/res/icons/prev.png b/python/res/icons/prev.png
new file mode 100644
index 00000000..15d1584b
--- /dev/null
+++ b/python/res/icons/prev.png
Binary files differ
diff --git a/python/res/jquery-latest.js b/python/res/jquery-latest.js
new file mode 100644
index 00000000..3747929d
--- /dev/null
+++ b/python/res/jquery-latest.js
@@ -0,0 +1,32 @@
+/*
+ * jQuery 1.2.3 - New Wave Javascript
+ *
+ * Copyright (c) 2008 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $
+ * $Rev: 4663 $
+ */
+(function(){if(window.jQuery)var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)if(elem.id!=match[3])return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}else
+selector=[];}}else
+return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value==undefined)return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else
+return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else
+selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){var option=options[i];if(option.selected){value=jQuery.browser.msie&&!option.attributes.value.specified?option.text:option.value;if(one)return value;values.push(value);}}return values;}else
+return(this[0].value||"").replace(/\r/g,"");}return undefined;}return this.each(function(){if(this.nodeType!=1)return;if(value.constructor==Array&&/radio|checkbox/.test(this.type))this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else
+this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else
+return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else
+jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==1){target=this;i=0;}for(;i<length;i++)if((options=arguments[i])!=null)for(var name in options){if(target===options[name])continue;if(deep&&options[name]&&typeof options[name]=="object"&&target[name]&&!options[name].nodeType)target[name]=jQuery.extend(target[name],options[name]);else if(options[name]!=undefined)target[name]=options[name];}return target;};var expando="jQuery"+(new Date()).getTime(),uuid=0,windowData={};var exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i;jQuery.extend({noConflict:function(deep){window.$=_$;if(deep)window.jQuery=_jQuery;return jQuery;},isFunction:function(fn){return!!fn&&typeof fn!="string"&&!fn.nodeName&&fn.constructor!=Array&&/function/i.test(fn+"");},isXMLDoc:function(elem){return elem.documentElement&&!elem.body||elem.tagName&&elem.ownerDocument&&!elem.ownerDocument.body;},globalEval:function(data){data=jQuery.trim(data);if(data){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.browser.msie)script.text=data;else
+script.appendChild(document.createTextNode(data));head.appendChild(script);head.removeChild(script);}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase();},cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id)id=elem[expando]=++uuid;if(name&&!jQuery.cache[id])jQuery.cache[id]={};if(data!=undefined)jQuery.cache[id][name]=data;return name?jQuery.cache[id][name]:id;},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id])break;if(!name)jQuery.removeData(elem);}}else{try{delete elem[expando];}catch(e){if(elem.removeAttribute)elem.removeAttribute(expando);}delete jQuery.cache[id];}},each:function(object,callback,args){if(args){if(object.length==undefined){for(var name in object)if(callback.apply(object[name],args)===false)break;}else
+for(var i=0,length=object.length;i<length;i++)if(callback.apply(object[i],args)===false)break;}else{if(object.length==undefined){for(var name in object)if(callback.call(object[name],name,object[name])===false)break;}else
+for(var i=0,length=object.length,value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}return object;},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value))value=value.call(elem,i);return value&&value.constructor==Number&&type=="curCSS"&&!exclude.test(name)?value+"px":value;},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className))elem.className+=(elem.className?" ":"")+className;});},remove:function(elem,classNames){if(elem.nodeType==1)elem.className=classNames!=undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return!jQuery.className.has(classNames,className);}).join(" "):"";},has:function(elem,className){return jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else
+jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&elem.style&&elem.style[name])ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)stack.unshift(a);for(var i=0;i<stack.length;i++)if(color(stack[i])){swap[i]=stack[i].style.display;stack[i].style.display="block";}ret=name=="display"&&swap[stack.length-1]!=null?"none":(getComputedStyle&&getComputedStyle.getPropertyValue(name))||"";for(var i=0;i<swap.length;i++)if(swap[i]!=null)stack[i].style.display=swap[i];}if(name=="opacity"&&ret=="")ret="1";}else if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase();});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var style=elem.style.left,runtimeStyle=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;elem.style.left=ret||0;ret=elem.style.pixelLeft+"px";elem.style.left=style;elem.runtimeStyle.left=runtimeStyle;}}return ret;},clean:function(elems,context){var ret=[];context=context||document;if(typeof context.createElement=='undefined')context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;jQuery.each(elems,function(i,elem){if(!elem)return;if(elem.constructor==Number)elem=elem.toString();if(typeof elem=="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||jQuery.browser.msie&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf("<table")&&tags.indexOf("<tbody")<0?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&tags.indexOf("<tbody")<0?div.childNodes:[];for(var j=tbody.length-1;j>=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else
+ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem.setAttribute(name,""+value);}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")for(var i=0,length=array.length;i<length;i++)ret.push(array[i]);else
+ret=array.slice(0);return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++)if(array[i]==elem)return i;return-1;},merge:function(first,second){if(jQuery.browser.msie){for(var i=0;second[i];i++)if(second[i].nodeType!=8)first.push(second[i]);}else
+for(var i=0;second[i];i++)first.push(second[i]);return first;},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i]);}}}catch(e){ret=array;}return ret;},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++)if(!inv&&callback(elems[i],i)||inv&&!callback(elems[i],i))ret.push(elems[i]);return ret;},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!==null&&value!=undefined){if(value.constructor!=Array)value=[value];ret=ret.concat(value);}}return ret;}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};var styleFloat=jQuery.browser.msie?"styleFloat":"cssFloat";jQuery.extend({boxModel:!jQuery.browser.msie||document.compatMode=="CSS1Compat",props:{"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,innerHTML:"innerHTML",className:"className",value:"value",disabled:"disabled",checked:"checked",readonly:"readOnly",selected:"selected",maxlength:"maxLength",selectedIndex:"selectedIndex",defaultValue:"defaultValue",tagName:"tagName",nodeName:"nodeName"}});jQuery.each({parent:function(elem){return elem.parentNode;},parents:function(elem){return jQuery.dir(elem,"parentNode");},next:function(elem){return jQuery.nth(elem,2,"nextSibling");},prev:function(elem){return jQuery.nth(elem,2,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},siblings:function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string")ret=jQuery.multiFilter(selector,ret);return this.pushStack(jQuery.unique(ret));};});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(){var args=arguments;return this.each(function(){for(var i=0,length=args.length;i<length;i++)jQuery(args[i])[original](this);});};});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1)this.removeAttribute(name);},addClass:function(classNames){jQuery.className.add(this,classNames);},removeClass:function(classNames){jQuery.className.remove(this,classNames);},toggleClass:function(classNames){jQuery.className[jQuery.className.has(this,classNames)?"remove":"add"](this,classNames);},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).r.length){jQuery("*",this).add(this).each(function(){jQuery.event.remove(this);jQuery.removeData(this);});if(this.parentNode)this.parentNode.removeChild(this);}},empty:function(){jQuery(">*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return i<m[3]-0;},gt:function(a,i,m){return i>m[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j<rl;j++){var n=m=="~"||m=="+"?ret[j].nextSibling:ret[j].firstChild;for(;n;n=n.nextSibling)if(n.nodeType==1){var id=jQuery.data(n);if(m=="~"&&merge[id])break;if(!nodeName||n.nodeName.toUpperCase()==nodeName){if(m=="~")merge[id]=true;r.push(n);}if(m=="+")break;}}ret=r;t=jQuery.trim(t.replace(re,""));foundToken=true;}}if(t&&!foundToken){if(!t.indexOf(",")){if(context==ret[0])ret.shift();done=jQuery.merge(done,ret);r=ret=[context];t=" "+t.substr(1,t.length);}else{var re2=quickID;var m=re2.exec(t);if(m){m=[0,m[2],m[3],m[1]];}else{re2=quickClass;m=re2.exec(t);}m[2]=m[2].replace(/\\/g,"");var elem=ret[ret.length-1];if(m[1]=="#"&&elem&&elem.getElementById&&!jQuery.isXMLDoc(elem)){var oid=elem.getElementById(m[2]);if((jQuery.browser.msie||jQuery.browser.opera)&&oid&&typeof oid.id=="string"&&oid.id!=m[2])oid=jQuery('[@id="'+m[2]+'"]',elem)[0];ret=r=oid&&(!m[3]||jQuery.nodeName(oid,m[3]))?[oid]:[];}else{for(var i=0;ret[i];i++){var tag=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];if(tag=="*"&&ret[i].nodeName.toLowerCase()=="object")tag="param";r=jQuery.merge(r,ret[i].getElementsByTagName(tag));}if(m[1]==".")r=jQuery.classFilter(r,m[2]);if(m[1]=="#"){var tmp=[];for(var i=0;r[i];i++)if(r[i].getAttribute("id")==m[2]){tmp=[r[i]];break;}r=tmp;}ret=r;}t=t.replace(re2,"");}}if(t){var val=jQuery.filter(t,r);ret=r=val.r;t=jQuery.trim(val.t);}}if(t)ret=[];if(ret&&context==ret[0])ret.shift();done=jQuery.merge(done,ret);return done;},classFilter:function(r,m,not){m=" "+m+" ";var tmp=[];for(var i=0;r[i];i++){var pass=(" "+r[i].className+" ").indexOf(m)>=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i<rl;i++){var a=r[i],z=a[jQuery.props[m[2]]||m[2]];if(z==null||/href|src|selected/.test(m[2]))z=jQuery.attr(a,m[2])||'';if((type==""&&!!z||type=="="&&z==m[5]||type=="!="&&z!=m[5]||type=="^="&&z&&!z.indexOf(m[5])||type=="$="&&z.substr(z.length-m[5].length)==m[5]||(type=="*="||type=="~=")&&z.indexOf(m[5])>=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i<rl;i++){var node=r[i],parentNode=node.parentNode,id=jQuery.data(parentNode);if(!merge[id]){var c=1;for(var n=parentNode.firstChild;n;n=n.nextSibling)if(n.nodeType==1)n.nodeIndex=c++;merge[id]=true;}var add=false;if(first==0){if(node.nodeIndex==last)add=true;}else if((node.nodeIndex-last)%first==0&&(node.nodeIndex-last)/first>=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval!=undefined)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else
+for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}if(jQuery.browser.msie)event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else
+jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i<document.styleSheets.length;i++)if(document.styleSheets[i].disabled){setTimeout(arguments.callee,0);return;}jQuery.ready();},false);if(jQuery.browser.safari){var numStyles;(function(){if(jQuery.isReady)return;if(document.readyState!="loaded"&&document.readyState!="complete"){setTimeout(arguments.callee,0);return;}if(numStyles===undefined)numStyles=jQuery("style, link[rel=stylesheet]").length;if(document.styleSheets.length!=numStyles){setTimeout(arguments.callee,0);return;}jQuery.ready();})();}jQuery.event.add(window,"load",jQuery.ready);}jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,"+"mousedown,mouseup,mousemove,mouseover,mouseout,change,select,"+"submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name);};});var withinElement=function(event,elem){var parent=event.relatedTarget;while(parent&&parent!=elem)try{parent=parent.parentNode;}catch(error){parent=elem;}return parent==elem;};jQuery(window).bind("unload",function(){jQuery("*").add(document).unbind();});jQuery.fn.extend({load:function(url,params,callback){if(jQuery.isFunction(url))return this.bind("load",url);var off=url.indexOf(" ");if(off>=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend)s.beforeSend(xml);if(s.global)jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else
+jQuery.handleError(s,xml,status);complete();if(s.async)xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xml){xml.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xml,s]);}function complete(){if(s.complete)s.complete(xml,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else
+for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else
+s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else
+e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i<timers.length;i++)if(!timers[i]())timers.splice(i--,1);if(!timers.length){clearInterval(jQuery.timerId);jQuery.timerId=null;}},13);}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(0,this.cur());if(this.prop=="width"||this.prop=="height")this.elem.style[this.prop]="1px";jQuery(this.elem).show();},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0);},step:function(gotoEnd){var t=(new Date()).getTime();if(gotoEnd||t>this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done&&jQuery.isFunction(this.options.complete))this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}return results;};})(); \ No newline at end of file
diff --git a/python/res/jquery.dimensions.min.js b/python/res/jquery.dimensions.min.js
new file mode 100644
index 00000000..34c06dee
--- /dev/null
+++ b/python/res/jquery.dimensions.min.js
@@ -0,0 +1,12 @@
+/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * $LastChangedDate: 2007-12-20 08:43:48 -0600 (Thu, 20 Dec 2007) $
+ * $Rev: 4257 $
+ *
+ * Version: 1.2
+ *
+ * Requires: jQuery 1.2+
+ */
+(function($){$.dimensions={version:'1.2'};$.each(['Height','Width'],function(i,name){$.fn['inner'+name]=function(){if(!this[0])return;var torl=name=='Height'?'Top':'Left',borr=name=='Height'?'Bottom':'Right';return this.is(':visible')?this[0]['client'+name]:num(this,name.toLowerCase())+num(this,'padding'+torl)+num(this,'padding'+borr);};$.fn['outer'+name]=function(options){if(!this[0])return;var torl=name=='Height'?'Top':'Left',borr=name=='Height'?'Bottom':'Right';options=$.extend({margin:false},options||{});var val=this.is(':visible')?this[0]['offset'+name]:num(this,name.toLowerCase())+num(this,'border'+torl+'Width')+num(this,'border'+borr+'Width')+num(this,'padding'+torl)+num(this,'padding'+borr);return val+(options.margin?(num(this,'margin'+torl)+num(this,'margin'+borr)):0);};});$.each(['Left','Top'],function(i,name){$.fn['scroll'+name]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(name=='Left'?val:$(window)['scrollLeft'](),name=='Top'?val:$(window)['scrollTop']()):this['scroll'+name]=val;}):this[0]==window||this[0]==document?self[(name=='Left'?'pageXOffset':'pageYOffset')]||$.boxModel&&document.documentElement['scroll'+name]||document.body['scroll'+name]:this[0]['scroll'+name];};});$.fn.extend({position:function(){var left=0,top=0,elem=this[0],offset,parentOffset,offsetParent,results;if(elem){offsetParent=this.offsetParent();offset=this.offset();parentOffset=offsetParent.offset();offset.top-=num(elem,'marginTop');offset.left-=num(elem,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&$.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return $(offsetParent);}});function num(el,prop){return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0;};})(jQuery); \ No newline at end of file
diff --git a/python/res/jquery.metadata.js b/python/res/jquery.metadata.js
new file mode 100644
index 00000000..6a984dbc
--- /dev/null
+++ b/python/res/jquery.metadata.js
@@ -0,0 +1,122 @@
+/*
+ * Metadata - jQuery plugin for parsing metadata from elements
+ *
+ * Copyright (c) 2006 John Resig, Yehuda Katz, J�örn Zaefferer, Paul McLanahan
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id$
+ *
+ */
+
+/**
+ * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
+ * in the JSON will become a property of the element itself.
+ *
+ * There are three supported types of metadata storage:
+ *
+ * attr: Inside an attribute. The name parameter indicates *which* attribute.
+ *
+ * class: Inside the class attribute, wrapped in curly braces: { }
+ *
+ * elem: Inside a child element (e.g. a script tag). The
+ * name parameter indicates *which* element.
+ *
+ * The metadata for an element is loaded the first time the element is accessed via jQuery.
+ *
+ * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
+ * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
+ *
+ * @name $.metadata.setType
+ *
+ * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
+ * @before $.metadata.setType("class")
+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
+ * @desc Reads metadata from the class attribute
+ *
+ * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
+ * @before $.metadata.setType("attr", "data")
+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
+ * @desc Reads metadata from a "data" attribute
+ *
+ * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
+ * @before $.metadata.setType("elem", "script")
+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
+ * @desc Reads metadata from a nested script element
+ *
+ * @param String type The encoding type
+ * @param String name The name of the attribute to be used to get metadata (optional)
+ * @cat Plugins/Metadata
+ * @descr Sets the type of encoding to be used when loading metadata for the first time
+ * @type undefined
+ * @see metadata()
+ */
+
+(function($) {
+
+$.extend({
+ metadata : {
+ defaults : {
+ type: 'class',
+ name: 'metadata',
+ cre: /({.*})/,
+ single: 'metadata'
+ },
+ setType: function( type, name ){
+ this.defaults.type = type;
+ this.defaults.name = name;
+ },
+ get: function( elem, opts ){
+ var settings = $.extend({},this.defaults,opts);
+ // check for empty string in single property
+ if ( !settings.single.length ) settings.single = 'metadata';
+
+ var data = $.data(elem, settings.single);
+ // returned cached data if it already exists
+ if ( data ) return data;
+
+ data = "{}";
+
+ if ( settings.type == "class" ) {
+ var m = settings.cre.exec( elem.className );
+ if ( m )
+ data = m[1];
+ } else if ( settings.type == "elem" ) {
+ if( !elem.getElementsByTagName )
+ return undefined;
+ var e = elem.getElementsByTagName(settings.name);
+ if ( e.length )
+ data = $.trim(e[0].innerHTML);
+ } else if ( elem.getAttribute != undefined ) {
+ var attr = elem.getAttribute( settings.name );
+ if ( attr )
+ data = attr;
+ }
+
+ if ( data.indexOf( '{' ) <0 )
+ data = "{" + data + "}";
+
+ data = eval("(" + data + ")");
+
+ $.data( elem, settings.single, data );
+ return data;
+ }
+ }
+});
+
+/**
+ * Returns the metadata object for the first member of the jQuery object.
+ *
+ * @name metadata
+ * @descr Returns element's metadata object
+ * @param Object opts An object contianing settings to override the defaults
+ * @type jQuery
+ * @cat Plugins/Metadata
+ */
+$.fn.metadata = function( opts ){
+ return $.metadata.get( this[0], opts );
+};
+
+})(jQuery); \ No newline at end of file
diff --git a/python/res/jquery.tablesorter.min.js b/python/res/jquery.tablesorter.min.js
new file mode 100644
index 00000000..64c70071
--- /dev/null
+++ b/python/res/jquery.tablesorter.min.js
@@ -0,0 +1,2 @@
+
+(function($){$.extend({tablesorter:new function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'.',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}var rows=table.tBodies[0].rows;if(table.tBodies[0].rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,cells[i]);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,node){var l=parsers.length;for(var i=1;i<l;i++){if(parsers[i].is($.trim(getElementText(table.config,node)),table,node)){return parsers[i];}}return parsers[0];}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=table.tBodies[0].rows[i],cols=[];cache.row.push($(c));for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c.cells[j]),table,c.cells[j]));}cols.push(i);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){if(!node)return"";var t="";if(config.textExtraction=="simple"){if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){t=node.childNodes[0].innerHTML;}else{t=node.innerHTML;}}else{if(typeof(config.textExtraction)=="function"){t=config.textExtraction(node);}else{t=$(node).text();}}return t;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){rows.push(r[n[i][checkCell]]);if(!table.config.appender){var o=r[n[i][checkCell]];var l=o.length;for(var j=0;j<l;j++){tableBody[0].appendChild(o[j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false,tableHeadersRows=[];for(var i=0;i<table.tHead.rows.length;i++){tableHeadersRows[i]=0;};$tableHeaders=$("thead th",table);$tableHeaders.each(function(index){this.count=0;this.column=index;this.order=formatSortingOrder(table.config.sortInitialOrder);if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(!this.sortDisabled){$(this).addClass(table.config.cssHeader);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){i=(v.toLowerCase()=="desc")?1:0;}else{i=(v==(0||1))?v:0;}return i;}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(getCachedSortType(table.config.parsers,c)=="text")?((order==0)?"sortText":"sortTextDesc"):((order==0)?"sortNumeric":"sortNumericDesc");var e="e"+i;dynamicExp+="var "+e+" = "+s+"(a["+c+"],b["+c+"]); ";dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function sortText(a,b){return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){$this.trigger("sortStart");var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){var $cell=$(this);var i=this.column;this.order=this.count++%2;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){var DECIMAL='\\'+config.decimal;var exp='/(^[+]?0('+DECIMAL+'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)'+DECIMAL+'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*'+DECIMAL+'0+$)/';return RegExp(exp).test($.trim(s));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}$("tr:visible",table.tBodies[0]).filter(':even').removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0]).end().filter(':odd').removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]);if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery); \ No newline at end of file
diff --git a/python/res/jquery.tablesorter.pager.css b/python/res/jquery.tablesorter.pager.css
new file mode 100644
index 00000000..8c8e9fca
--- /dev/null
+++ b/python/res/jquery.tablesorter.pager.css
@@ -0,0 +1,25 @@
+div.tablesorterPager {
+ padding: 10px 0 10px 0;
+ background-color: #D6D2C2;
+ text-align: center;
+}
+div.tablesorterPager span {
+ padding: 0 5px 0 5px;
+}
+div.tablesorterPager input.prev {
+ width: auto;
+ margin-right: 10px;
+}
+div.tablesorterPager input.next {
+ width: auto;
+ margin-left: 10px;
+}
+div.tablesorterPager input {
+ font-size: 8px;
+ width: 50px;
+ border: 1px solid #330000;
+ text-align: center;
+}
+
+
+ \ No newline at end of file
diff --git a/python/res/jquery.tablesorter.pager.js b/python/res/jquery.tablesorter.pager.js
new file mode 100644
index 00000000..cce6ea26
--- /dev/null
+++ b/python/res/jquery.tablesorter.pager.js
@@ -0,0 +1,184 @@
+(function($) {
+ $.extend({
+ tablesorterPager: new function() {
+
+ function updatePageDisplay(c) {
+ var s = $(c.cssPageDisplay,c.container).val((c.page+1) + c.seperator + c.totalPages);
+ }
+
+ function setPageSize(table,size) {
+ var c = table.config;
+ c.size = size;
+ c.totalPages = Math.ceil(c.totalRows / c.size);
+ c.pagerPositionSet = false;
+ moveToPage(table);
+ fixPosition(table);
+ }
+
+ function fixPosition(table) {
+ var c = table.config;
+ if(!c.pagerPositionSet && c.positionFixed) {
+ var c = table.config, o = $(table);
+ if(o.offset) {
+ c.container.css({
+ top: o.offset().top + o.height() + 'px',
+ position: 'absolute'
+ });
+ }
+ c.pagerPositionSet = true;
+ }
+ }
+
+ function moveToFirstPage(table) {
+ var c = table.config;
+ c.page = 0;
+ moveToPage(table);
+ }
+
+ function moveToLastPage(table) {
+ var c = table.config;
+ c.page = (c.totalPages-1);
+ moveToPage(table);
+ }
+
+ function moveToNextPage(table) {
+ var c = table.config;
+ c.page++;
+ if(c.page >= (c.totalPages-1)) {
+ c.page = (c.totalPages-1);
+ }
+ moveToPage(table);
+ }
+
+ function moveToPrevPage(table) {
+ var c = table.config;
+ c.page--;
+ if(c.page <= 0) {
+ c.page = 0;
+ }
+ moveToPage(table);
+ }
+
+
+ function moveToPage(table) {
+ var c = table.config;
+ if(c.page < 0 || c.page > (c.totalPages-1)) {
+ c.page = 0;
+ }
+
+ renderTable(table,c.rowsCopy);
+ }
+
+ function renderTable(table,rows) {
+
+ var c = table.config;
+ var l = rows.length;
+ var s = (c.page * c.size);
+ var e = (s + c.size);
+ if(e > rows.length ) {
+ e = rows.length;
+ }
+
+
+ var tableBody = $(table.tBodies[0]);
+
+ // clear the table body
+
+ $.tablesorter.clearTableBody(table);
+
+ for(var i = s; i < e; i++) {
+
+ //tableBody.append(rows[i]);
+
+ var o = rows[i];
+ var l = o.length;
+ for(var j=0; j < l; j++) {
+
+ tableBody[0].appendChild(o[j]);
+
+ }
+ }
+
+ fixPosition(table,tableBody);
+
+ $(table).trigger("applyWidgets");
+
+ if( c.page >= c.totalPages ) {
+ moveToLastPage(table);
+ }
+
+ updatePageDisplay(c);
+ }
+
+ this.appender = function(table,rows) {
+
+ var c = table.config;
+
+ c.rowsCopy = rows;
+ c.totalRows = rows.length;
+ c.totalPages = Math.ceil(c.totalRows / c.size);
+
+ renderTable(table,rows);
+ };
+
+ this.defaults = {
+ size: 10,
+ offset: 0,
+ page: 0,
+ totalRows: 0,
+ totalPages: 0,
+ container: null,
+ cssNext: '.next',
+ cssPrev: '.prev',
+ cssFirst: '.first',
+ cssLast: '.last',
+ cssPageDisplay: '.pagedisplay',
+ cssPageSize: '.pagesize',
+ seperator: "/",
+ positionFixed: true,
+ appender: this.appender
+ };
+
+ this.construct = function(settings) {
+
+ return this.each(function() {
+
+ config = $.extend(this.config, $.tablesorterPager.defaults, settings);
+
+ var table = this, pager = config.container;
+
+ $(this).trigger("appendCache");
+
+ config.size = parseInt($(".pagesize",pager).val());
+
+ $(config.cssFirst,pager).click(function() {
+ moveToFirstPage(table);
+ return false;
+ });
+ $(config.cssNext,pager).click(function() {
+ moveToNextPage(table);
+ return false;
+ });
+ $(config.cssPrev,pager).click(function() {
+ moveToPrevPage(table);
+ return false;
+ });
+ $(config.cssLast,pager).click(function() {
+ moveToLastPage(table);
+ return false;
+ });
+ $(config.cssPageSize,pager).change(function() {
+ setPageSize(table,parseInt($(this).val()));
+ return false;
+ });
+ });
+ };
+
+ }
+ });
+ // extend plugin scope
+ $.fn.extend({
+ tablesorterPager: $.tablesorterPager.construct
+ });
+
+})(jQuery); \ No newline at end of file
diff --git a/python/res/style.css b/python/res/style.css
new file mode 100644
index 00000000..eb41f70c
--- /dev/null
+++ b/python/res/style.css
@@ -0,0 +1,39 @@
+/* tables */
+table.tablesorter {
+ font-family:arial;
+ background-color: #CDCDCD;
+ margin:10px 0pt 15px;
+ font-size: 8pt;
+ width: 100%;
+ text-align: left;
+}
+table.tablesorter thead tr th, table.tablesorter tfoot tr th {
+ background-color: #e6EEEE;
+ border: 1px solid #FFF;
+ font-size: 8pt;
+ padding: 4px;
+}
+table.tablesorter thead tr .header {
+ background-image: url(bg.gif);
+ background-repeat: no-repeat;
+ background-position: center right;
+ cursor: pointer;
+}
+table.tablesorter tbody td {
+ color: #3D3D3D;
+ padding: 4px;
+ background-color: #FFF;
+ vertical-align: top;
+}
+table.tablesorter tbody tr.odd td {
+ background-color:#F0F0F6;
+}
+table.tablesorter thead tr .headerSortUp {
+ background-image: url(asc.gif);
+}
+table.tablesorter thead tr .headerSortDown {
+ background-image: url(desc.gif);
+}
+table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
+background-color: #8dbdd8;
+}
diff --git a/python/server.py b/python/server.py
new file mode 100644
index 00000000..13182836
--- /dev/null
+++ b/python/server.py
@@ -0,0 +1,196 @@
+# -*- coding: utf-8 -*-
+
+import ledger
+import cgi
+import sys
+import types
+import posixpath
+import urllib
+import shutil
+import os
+import re
+
+from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
+from os.path import exists, join, isfile
+
+from Cheetah.Template import Template
+from Cheetah.Filters import Filter, WebSafe
+
+webroot = join(os.getcwd(), 'python', 'res')
+
+class UnicodeFilter(Filter):
+ def filter(self, s, **kargs):
+ return Filter.filter(self, s, str=unicode, **kargs)
+
+def strip(value):
+ #return re.sub('\n', '<br />', value.strip_annotations().to_string())
+ return value.strip_annotations().to_string()
+
+templateDef = '''#encoding utf-8
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>$title</title>
+ <link rel="stylesheet" href="/style.css" type="text/css" media="print, projection, screen" />
+ <script type="text/javascript" src="/jquery-latest.js"></script>
+ <script type="text/javascript" src="/jquery.tablesorter.min.js"></script>
+ <script type="text/javascript" src="/jquery.tablesorter.pager.js"></script>
+ <script type="text/javascript" src="/jquery.dimensions.min.js"></script>
+ <script type="text/javascript">
+ \$(function() {
+ \$("table")
+ .tablesorter({textExtraction: 'complex',
+ widthFixed: true,
+ widgets: ['zebra']})
+ .tablesorterPager({size: 100,
+ container: \$("\#pager")});
+ });
+ </script>
+ </head>
+ <body>
+ <div id="main">
+ <h1>Register report</h1>
+ <table id="register" cellspacing="1" class="tablesorter">
+ <thead>
+ <tr>
+ <th>Date</th>
+ <th>Payee</th>
+ <th>Account</th>
+ <th>Amount</th>
+ <th>Total</th>
+ </tr>
+ </thead>
+ <tfoot>
+ <tr>
+ <th>Date</th>
+ <th>Payee</th>
+ <th>Account</th>
+ <th>Amount</th>
+ <th>Total</th>
+ </tr>
+ </tfoot>
+ <tbody>
+ #for $post in $posts
+ #set $total = $total + $post.amount
+ <tr>
+ <!--<td>${$post.xact.date if $post.xact is not $last_xact else $empty}</td>
+ <td>${$post.xact.payee if $post.xact is not $last_xact else $empty}</td>-->
+ <td>$post.xact.date</td>
+ <td>$post.xact.payee</td>
+ <td>$post.account</td>
+ <td>${strip($post.amount)}</td>
+ <td>${strip($total)}</td>
+ </tr>
+ #set $last_xact = $post.xact
+ #end for
+ </tbody>
+ </table>
+ <div id="pager" class="pager">
+ <form>
+ <img src="/icons/first.png" class="first"/>
+ <img src="/icons/prev.png" class="prev"/>
+ <input type="text" class="pagedisplay"/>
+ <img src="/icons/next.png" class="next"/>
+ <img src="/icons/last.png" class="last"/>
+ <select class="pagesize">
+ <option selected="selected" value="40">40</option>
+ <option value="100">100</option>
+ <option value="200">200</option>
+ <option value="300">300</option>
+ </select>
+ </form>
+ </div>
+ </body>
+ </html>
+'''
+
+class LedgerHandler(BaseHTTPRequestHandler):
+ def __init__(self, *args):
+ self.journal = ledger.Journal(sys.argv[1])
+ BaseHTTPRequestHandler.__init__(self, *args)
+
+ def do_GET(self):
+ path = self.translate_path(self.path)
+
+ if path and exists(path) and isfile(path):
+ self.copyfile(open(path), self.wfile)
+ else:
+ tmpl = Template(templateDef, filter=UnicodeFilter)
+
+ tmpl.title = 'Ledger Journal'
+ tmpl.posts = self.journal.collect(sys.argv[2])
+ tmpl.total = ledger.Value(0)
+ tmpl.strip = strip
+ tmpl.last_xact = None
+ tmpl.empty = ""
+
+ html = unicode(tmpl)
+ html = html.encode('utf-8')
+ self.wfile.write(html)
+
+ def do_POST(self):
+ print "Saw a POST request!"
+ try:
+ ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
+ if ctype == 'multipart/form-data':
+ query = cgi.parse_multipart(self.rfile, pdict)
+ self.send_response(301)
+ self.end_headers()
+ except Exception:
+ print "Saw exception in POST handler"
+
+ # This code is straight from SimpleHTTPServer.py
+ def copyfile(self, source, outputfile):
+ """Copy all data between two file objects.
+
+ The SOURCE argument is a file object open for reading
+ (or anything with a read() method) and the DESTINATION
+ argument is a file object open for writing (or
+ anything with a write() method).
+
+ The only reason for overriding this would be to change
+ the block size or perhaps to replace newlines by CRLF
+ -- note however that this the default server uses this
+ to copy binary data as well.
+
+ """
+ shutil.copyfileobj(source, outputfile)
+
+ def translate_path(self, path):
+ """Translate a /-separated PATH to the local filename syntax.
+
+ Components that mean special things to the local file system
+ (e.g. drive or directory names) are ignored. (XXX They should
+ probably be diagnosed.)
+
+ """
+ # abandon query parameters
+ path = path.split('?',1)[0]
+ path = path.split('#',1)[0]
+ path = posixpath.normpath(urllib.unquote(path))
+ words = path.split('/')
+ words = filter(None, words)
+ path = webroot
+ for word in words:
+ drive, word = os.path.splitdrive(word)
+ head, word = os.path.split(word)
+ if word in (os.curdir, os.pardir): continue
+ path = os.path.join(path, word)
+ return path
+
+def main(*args):
+ try:
+ port = 9000
+ server = HTTPServer(('', port), LedgerHandler)
+ print "Local HTTP server listening on port %d... (Control-C to exit)" \
+ % port
+ server.serve_forever()
+ except KeyboardInterrupt:
+ print "Shutting down server"
+ server.socket.close()
+
+if __name__ == '__main__':
+ if len(sys.argv) < 3:
+ print "usage: server.py <DATA-FILE> <REPORT-QUERY>"
+ sys.exit(1)
+ main()
diff --git a/qif.cc b/qif.cc
deleted file mode 100644
index faad30ca..00000000
--- a/qif.cc
+++ /dev/null
@@ -1,250 +0,0 @@
-#include "journal.h"
-#include "qif.h"
-#include "datetime.h"
-#include "error.h"
-#include "util.h"
-
-#include <cstring>
-#include <memory>
-
-namespace ledger {
-
-#define MAX_LINE 1024
-
-static char line[MAX_LINE + 1];
-static std::string path;
-static unsigned int src_idx;
-static unsigned int linenum;
-
-static inline char * get_line(std::istream& in) {
- in.getline(line, MAX_LINE);
- int len = std::strlen(line);
- if (line[len - 1] == '\r')
- line[len - 1] = '\0';
- linenum++;
- return line;
-}
-
-bool qif_parser_t::test(std::istream& in) const
-{
- char magic[sizeof(unsigned int) + 1];
- in.read(magic, sizeof(unsigned int));
- magic[sizeof(unsigned int)] = '\0';
- in.clear();
- in.seekg(0, std::ios::beg);
-
- return (std::strcmp(magic, "!Typ") == 0 ||
- std::strcmp(magic, "\n!Ty") == 0 ||
- std::strcmp(magic, "\r\n!T") == 0);
-}
-
-unsigned int qif_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
-{
- std::auto_ptr<entry_t> entry;
- std::auto_ptr<amount_t> amount;
-
- transaction_t * xact;
- unsigned int count = 0;
- account_t * misc = NULL;
- commodity_t * def_commodity = NULL;
- bool saw_splits = false;
- bool saw_category = false;
- transaction_t * total = NULL;
-
- entry.reset(new entry_t);
- xact = new transaction_t(master);
- entry->add_transaction(xact);
-
- path = journal->sources.back();
- src_idx = journal->sources.size() - 1;
- linenum = 1;
-
- istream_pos_type beg_pos = 0;
- unsigned long beg_line = 0;
-
-#define SET_BEG_POS_AND_LINE() \
- if (! beg_line) { \
- beg_pos = in.tellg(); \
- beg_line = linenum; \
- }
-
- while (in.good() && ! in.eof()) {
- char c;
- in.get(c);
- switch (c) {
- case ' ':
- case '\t':
- if (peek_next_nonws(in) != '\n') {
- get_line(in);
- throw new parse_error("Line begins with whitespace");
- }
- // fall through...
-
- case '\n':
- linenum++;
- case '\r': // skip blank lines
- break;
-
- case '!':
- get_line(in);
-
- if (std::strcmp(line, "Type:Invst") == 0 ||
- std::strcmp(line, "Account") == 0 ||
- std::strcmp(line, "Type:Cat") == 0 ||
- std::strcmp(line, "Type:Class") == 0 ||
- std::strcmp(line, "Type:Memorized") == 0)
- throw new parse_error(std::string("QIF files of type ") + line +
- " are not supported.");
- break;
-
- case 'D':
- SET_BEG_POS_AND_LINE();
- get_line(in);
- entry->_date = line;
- break;
-
- case 'T':
- case '$': {
- SET_BEG_POS_AND_LINE();
- get_line(in);
- xact->amount.parse(line);
-
- unsigned char flags = xact->amount.commodity().flags();
- unsigned char prec = xact->amount.commodity().precision();
-
- if (! def_commodity) {
- def_commodity = commodity_t::find_or_create("$");
- assert(def_commodity);
- }
- xact->amount.set_commodity(*def_commodity);
-
- def_commodity->add_flags(flags);
- if (prec > def_commodity->precision())
- def_commodity->set_precision(prec);
-
- if (c == '$') {
- saw_splits = true;
- xact->amount.negate();
- } else {
- total = xact;
- }
- break;
- }
-
- case 'C':
- SET_BEG_POS_AND_LINE();
- c = in.peek();
- if (c == '*' || c == 'X') {
- in.get(c);
- xact->state = transaction_t::CLEARED;
- }
- break;
-
- case 'N':
- SET_BEG_POS_AND_LINE();
- get_line(in);
- entry->code = line;
- break;
-
- case 'P':
- case 'M':
- case 'L':
- case 'S':
- case 'E': {
- SET_BEG_POS_AND_LINE();
- get_line(in);
-
- switch (c) {
- case 'P':
- entry->payee = line;
- break;
-
- case 'S':
- xact = new transaction_t(NULL);
- entry->add_transaction(xact);
- // fall through...
- case 'L': {
- int len = std::strlen(line);
- if (line[len - 1] == ']')
- line[len - 1] = '\0';
- xact->account = journal->find_account(line[0] == '[' ?
- line + 1 : line);
- if (c == 'L')
- saw_category = true;
- break;
- }
-
- case 'M':
- case 'E':
- xact->note = line;
- break;
- }
- break;
- }
-
- case 'A':
- SET_BEG_POS_AND_LINE();
- // jww (2004-08-19): these are ignored right now
- get_line(in);
- break;
-
- case '^': {
- account_t * other;
- if (xact->account == master) {
- if (! misc)
- misc = journal->find_account("Miscellaneous");
- other = misc;
- } else {
- other = master;
- }
-
- if (total && saw_category) {
- if (! saw_splits)
- total->amount.negate(); // negate, to show correct flow
- else
- total->account = other;
- }
-
- if (! saw_splits) {
- transaction_t * nxact = new transaction_t(other);
- // The amount doesn't need to be set because the code below
- // will balance this transaction against the other.
- entry->add_transaction(nxact);
- }
-
- if (journal->add_entry(entry.get())) {
- entry->src_idx = src_idx;
- entry->beg_pos = beg_pos;
- entry->beg_line = beg_line;
- entry->end_pos = in.tellg();
- entry->end_line = linenum;
- entry.release();
- count++;
- }
-
- // reset things for the next entry
- entry.reset(new entry_t);
- xact = new transaction_t(master);
- entry->add_transaction(xact);
-
- saw_splits = false;
- saw_category = false;
- total = NULL;
- beg_line = 0;
- break;
- }
-
- default:
- get_line(in);
- break;
- }
- }
-
- return count;
-}
-
-} // namespace ledger
diff --git a/qif.h b/qif.h
deleted file mode 100644
index d8c52576..00000000
--- a/qif.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _QIF_H
-#define _QIF_H
-
-#include "parser.h"
-
-namespace ledger {
-
-class qif_parser_t : public parser_t
-{
- public:
- virtual bool test(std::istream& in) const;
-
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
-};
-
-} // namespace ledger
-
-#endif // _QIF_H
diff --git a/quotes.cc b/quotes.cc
deleted file mode 100644
index a8fbfbc5..00000000
--- a/quotes.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-#include "quotes.h"
-#include "datetime.h"
-#include "error.h"
-#include "debug.h"
-
-#include <fstream>
-#include <cstdlib>
-#include <cstdio>
-
-namespace ledger {
-
-void quotes_by_script::operator()(commodity_base_t& commodity,
- const datetime_t& moment,
- const datetime_t& date,
- const datetime_t& last,
- amount_t& price)
-{
- DEBUG_CLASS("ledger.quotes.download");
-
- DEBUG_PRINT_("commodity: " << commodity.symbol);
- DEBUG_PRINT_TIME_(datetime_t::now);
- DEBUG_PRINT_TIME_(moment);
- DEBUG_PRINT_TIME_(date);
- DEBUG_PRINT_TIME_(last);
- if (commodity.history)
- DEBUG_PRINT_TIME_(commodity.history->last_lookup);
- DEBUG_PRINT_("pricing_leeway is " << pricing_leeway);
-
- if ((commodity.history &&
- (datetime_t::now - commodity.history->last_lookup) < pricing_leeway) ||
- (datetime_t::now - last) < pricing_leeway ||
- (price && moment > date && (moment - date) <= pricing_leeway))
- return;
-
- using namespace std;
-
- DEBUG_PRINT_("downloading quote for symbol " << commodity.symbol);
-
- char buf[256];
- buf[0] = '\0';
-
- bool success = true;
-
- if (FILE * fp = popen((string("getquote \"") +
- commodity.symbol + "\"").c_str(), "r")) {
- if (feof(fp) || ! fgets(buf, 255, fp))
- success = false;
- if (pclose(fp) != 0)
- success = false;
- } else {
- success = false;
- }
-
- if (success && buf[0]) {
- char * p = strchr(buf, '\n');
- if (p) *p = '\0';
-
- DEBUG_PRINT_("downloaded quote: " << buf);
-
- price.parse(buf);
- commodity.add_price(datetime_t::now, price);
-
- commodity.history->last_lookup = datetime_t::now;
- cache_dirty = true;
-
- if (price && ! price_db.empty()) {
-#if defined(__GNUG__) && __GNUG__ < 3
- ofstream database(price_db.c_str(), ios::out | ios::app);
-#else
- ofstream database(price_db.c_str(), ios_base::out | ios_base::app);
-#endif
- database << "P " << datetime_t::now.to_string("%Y/%m/%d %H:%M:%S")
- << " " << commodity.symbol << " " << price << endl;
- }
- } else {
- throw new error(std::string("Failed to download price for '") +
- commodity.symbol + "' (command: \"getquote " +
- commodity.symbol + "\")");
- }
-}
-
-} // namespace ledger
diff --git a/quotes.h b/quotes.h
deleted file mode 100644
index 12164b14..00000000
--- a/quotes.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef _QUOTES_H
-#define _QUOTES_H
-
-#include "amount.h"
-
-namespace ledger {
-
-class quotes_by_script : public commodity_base_t::updater_t
-{
- std::string price_db;
- unsigned long pricing_leeway;
- bool& cache_dirty;
-
- public:
- quotes_by_script(std::string _price_db,
- unsigned long _pricing_leeway,
- bool& _cache_dirty)
- : price_db(_price_db), pricing_leeway(_pricing_leeway),
- cache_dirty(_cache_dirty) {}
-
- virtual void operator()(commodity_base_t& commodity,
- const datetime_t& moment,
- const datetime_t& date,
- const datetime_t& last,
- amount_t& price);
-};
-
-} // namespace ledger
-
-#endif // _QUOTES_H
diff --git a/reconcile.cc b/reconcile.cc
deleted file mode 100644
index 5b6dba24..00000000
--- a/reconcile.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-#include "reconcile.h"
-#include "walk.h"
-
-namespace ledger {
-
-#define xact_next(x) ((transaction_t *)transaction_xdata(*x).ptr)
-#define xact_next_ptr(x) ((transaction_t **)&transaction_xdata(*x).ptr)
-
-static bool search_for_balance(amount_t& amount,
- transaction_t ** prev, transaction_t * next)
-{
- for (; next; next = xact_next(next)) {
- transaction_t * temp = *prev;
- *prev = next;
-
- amount -= next->amount;
- if (! amount ||
- search_for_balance(amount, xact_next_ptr(next), xact_next(next)))
- return true;
- amount += next->amount;
-
- *prev = temp;
- }
- return false;
-}
-
-void reconcile_transactions::push_to_handler(transaction_t * first)
-{
- for (; first; first = xact_next(first))
- item_handler<transaction_t>::operator()(*first);
-
- item_handler<transaction_t>::flush();
-}
-
-void reconcile_transactions::flush()
-{
- value_t cleared_balance;
- value_t pending_balance;
-
- transaction_t * first = NULL;
- transaction_t ** last_ptr = &first;
-
- bool found_pending = false;
- for (transactions_list::iterator x = xacts.begin();
- x != xacts.end();
- x++) {
- if (! cutoff || (*x)->date() < cutoff) {
- switch ((*x)->state) {
- case transaction_t::CLEARED:
- cleared_balance += (*x)->amount;
- break;
- case transaction_t::UNCLEARED:
- case transaction_t::PENDING:
- pending_balance += (*x)->amount;
- *last_ptr = *x;
- last_ptr = xact_next_ptr(*x);
- break;
- }
- }
- }
-
- if (cleared_balance.type >= value_t::BALANCE)
- throw new error("Cannot reconcile accounts with multiple commodities");
-
- cleared_balance.cast(value_t::AMOUNT);
- balance.cast(value_t::AMOUNT);
-
- commodity_t& cb_comm = ((amount_t *) cleared_balance.data)->commodity();
- commodity_t& b_comm = ((amount_t *) balance.data)->commodity();
-
- balance -= cleared_balance;
- if (balance.type >= value_t::BALANCE)
- throw new error(std::string("Reconcile balance is not of the same commodity ('") +
- b_comm.symbol() + "' != '" + cb_comm.symbol() + "')");
-
- // If the amount to reconcile is the same as the pending balance,
- // then assume an exact match and return the results right away.
- amount_t to_reconcile = *((amount_t *) balance.data);
- pending_balance.cast(value_t::AMOUNT);
- if (to_reconcile == *((amount_t *) pending_balance.data) ||
- search_for_balance(to_reconcile, &first, first)) {
- push_to_handler(first);
- } else {
- throw new error("Could not reconcile account!");
- }
-}
-
-} // namespace ledger
diff --git a/reconcile.h b/reconcile.h
deleted file mode 100644
index 7fd0d581..00000000
--- a/reconcile.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _RECONCILE_H
-#define _RECONCILE_H
-
-#include "value.h"
-#include "walk.h"
-
-namespace ledger {
-
-class reconcile_transactions : public item_handler<transaction_t>
-{
- value_t balance;
- datetime_t cutoff;
-
- transactions_list xacts;
-
- public:
- reconcile_transactions(item_handler<transaction_t> * handler,
- const value_t& _balance,
- const datetime_t& _cutoff)
- : item_handler<transaction_t>(handler),
- balance(_balance), cutoff(_cutoff) {}
-
- void push_to_handler(transaction_t * first);
-
- virtual void flush();
- virtual void operator()(transaction_t& xact) {
- xacts.push_back(&xact);
- }
-};
-
-} // namespace ledger
-
-#endif // _RECONCILE_H
diff --git a/report.cc b/report.cc
deleted file mode 100644
index 90259440..00000000
--- a/report.cc
+++ /dev/null
@@ -1,413 +0,0 @@
-#include "report.h"
-
-namespace ledger {
-
-report_t::report_t()
-{
- ledger::amount_expr = "@a";
- ledger::total_expr = "@O";
-
- predicate = "";
- secondary_predicate = "";
- display_predicate = "";
- descend_expr = "";
-
- budget_flags = BUDGET_NO_BUDGET;
-
- head_entries = 0;
- tail_entries = 0;
-
- show_collapsed = false;
- show_subtotal = false;
- show_totals = false;
- show_related = false;
- show_all_related = false;
- show_inverted = false;
- show_empty = false;
- days_of_the_week = false;
- by_payee = false;
- comm_as_payee = false;
- code_as_payee = false;
- show_revalued = false;
- show_revalued_only = false;
- keep_price = false;
- keep_date = false;
- keep_tag = false;
- entry_sort = false;
- sort_all = false;
-}
-
-void
-report_t::regexps_to_predicate(const std::string& command,
- std::list<std::string>::const_iterator begin,
- std::list<std::string>::const_iterator end,
- const bool account_regexp,
- const bool add_account_short_masks,
- const bool logical_and)
-{
- std::string regexps[2];
-
- assert(begin != end);
-
- // Treat the remaining command-line arguments as regular
- // expressions, used for refining report results.
-
- for (std::list<std::string>::const_iterator i = begin;
- i != end;
- i++)
- if ((*i)[0] == '-') {
- if (! regexps[1].empty())
- regexps[1] += "|";
- regexps[1] += (*i).substr(1);
- }
- else if ((*i)[0] == '+') {
- if (! regexps[0].empty())
- regexps[0] += "|";
- regexps[0] += (*i).substr(1);
- }
- else {
- if (! regexps[0].empty())
- regexps[0] += "|";
- regexps[0] += *i;
- }
-
- for (int i = 0; i < 2; i++) {
- if (regexps[i].empty())
- continue;
-
- if (! predicate.empty())
- predicate += logical_and ? "&" : "|";
-
- int add_predicate = 0; // 1 adds /.../, 2 adds ///.../
- if (i == 1) {
- predicate += "!";
- }
- else if (add_account_short_masks) {
- if (regexps[i].find(':') != std::string::npos ||
- regexps[i].find('.') != std::string::npos ||
- regexps[i].find('*') != std::string::npos ||
- regexps[i].find('+') != std::string::npos ||
- regexps[i].find('[') != std::string::npos ||
- regexps[i].find('(') != std::string::npos) {
- show_subtotal = true;
- add_predicate = 1;
- } else {
- add_predicate = 2;
- }
- }
- else {
- add_predicate = 1;
- }
-
- if (i != 1 && command == "b" && account_regexp) {
- if (! show_related && ! show_all_related) {
- if (! display_predicate.empty())
- display_predicate += "&";
- if (! show_empty)
- display_predicate += "T&";
-
- if (add_predicate == 2)
- display_predicate += "//";
- display_predicate += "/(?:";
- display_predicate += regexps[i];
- display_predicate += ")/";
- }
- else if (! show_empty) {
- if (! display_predicate.empty())
- display_predicate += "&";
- display_predicate += "T";
- }
- }
-
- if (! account_regexp)
- predicate += "/";
- predicate += "/(?:";
- predicate += regexps[i];
- predicate += ")/";
- }
-}
-
-void report_t::process_options(const std::string& command,
- strings_list::iterator arg,
- strings_list::iterator args_end)
-{
- // Configure some other options depending on report type
-
- if (command == "p" || command == "e" || command == "w") {
- show_related =
- show_all_related = true;
- }
- else if (command == "E") {
- show_subtotal = true;
- }
- else if (show_related) {
- if (command == "r") {
- show_inverted = true;
- } else {
- show_subtotal = true;
- show_all_related = true;
- }
- }
-
- if (command != "b" && command != "r")
- amount_t::keep_base = true;
-
- // Process remaining command-line arguments
-
- if (command != "e") {
- // Treat the remaining command-line arguments as regular
- // expressions, used for refining report results.
-
- std::list<std::string>::iterator i = arg;
- for (; i != args_end; i++)
- if (*i == "--")
- break;
-
- if (i != arg)
- regexps_to_predicate(command, arg, i, true,
- (command == "b" && ! show_subtotal &&
- display_predicate.empty()));
- if (i != args_end && ++i != args_end)
- regexps_to_predicate(command, i, args_end);
- }
-
- // Setup the default value for the display predicate
-
- if (display_predicate.empty()) {
- if (command == "b") {
- if (! show_empty)
- display_predicate = "T";
- if (! show_subtotal) {
- if (! display_predicate.empty())
- display_predicate += "&";
- display_predicate += "l<=1";
- }
- }
- else if (command == "E") {
- display_predicate = "t";
- }
- else if (command == "r" && ! show_empty) {
- display_predicate = "a";
- }
- }
-
- DEBUG_PRINT("ledger.config.predicates", "Predicate: " << predicate);
- DEBUG_PRINT("ledger.config.predicates", "Display P: " << display_predicate);
-
- // Setup the values of %t and %T, used in format strings
-
- if (! amount_expr.empty())
- ledger::amount_expr = amount_expr;
- if (! total_expr.empty())
- ledger::total_expr = total_expr;
-
- // Now setup the various formatting strings
-
- if (! date_output_format.empty())
- date_t::output_format = date_output_format;
-
- amount_t::keep_price = keep_price;
- amount_t::keep_date = keep_date;
- amount_t::keep_tag = keep_tag;
-
- if (! report_period.empty() && ! sort_all)
- entry_sort = true;
-}
-
-item_handler<transaction_t> *
-report_t::chain_xact_handlers(const std::string& command,
- item_handler<transaction_t> * base_formatter,
- journal_t * journal,
- account_t * master,
- std::list<item_handler<transaction_t> *>& ptrs)
-{
- bool remember_components = false;
-
- item_handler<transaction_t> * formatter = NULL;
-
- ptrs.push_back(formatter = base_formatter);
-
- // format_transactions write each transaction received to the
- // output stream.
- if (! (command == "b" || command == "E")) {
- // truncate_entries cuts off a certain number of _entries_ from
- // being displayed. It does not affect calculation.
- if (head_entries || tail_entries)
- ptrs.push_back(formatter =
- new truncate_entries(formatter,
- head_entries, tail_entries));
-
- // filter_transactions will only pass through transactions
- // matching the `display_predicate'.
- if (! display_predicate.empty())
- ptrs.push_back(formatter =
- new filter_transactions(formatter,
- display_predicate));
-
- // calc_transactions computes the running total. When this
- // appears will determine, for example, whether filtered
- // transactions are included or excluded from the running total.
- ptrs.push_back(formatter = new calc_transactions(formatter));
-
- // component_transactions looks for reported transaction that
- // match the given `descend_expr', and then reports the
- // transactions which made up the total for that reported
- // transaction.
- if (! descend_expr.empty()) {
- std::list<std::string> descend_exprs;
-
- std::string::size_type beg = 0;
- for (std::string::size_type pos = descend_expr.find(';');
- pos != std::string::npos;
- beg = pos + 1, pos = descend_expr.find(';', beg))
- descend_exprs.push_back(std::string(descend_expr, beg, pos - beg));
- descend_exprs.push_back(std::string(descend_expr, beg));
-
- for (std::list<std::string>::reverse_iterator i =
- descend_exprs.rbegin();
- i != descend_exprs.rend();
- i++)
- ptrs.push_back(formatter =
- new component_transactions(formatter, *i));
-
- remember_components = true;
- }
-
- // reconcile_transactions will pass through only those
- // transactions which can be reconciled to a given balance
- // (calculated against the transactions which it receives).
- if (! reconcile_balance.empty()) {
- datetime_t cutoff = datetime_t::now;
- if (! reconcile_date.empty())
- cutoff = reconcile_date;
- ptrs.push_back(formatter =
- new reconcile_transactions
- (formatter, value_t(reconcile_balance), cutoff));
- }
-
- // filter_transactions will only pass through transactions
- // matching the `secondary_predicate'.
- if (! secondary_predicate.empty())
- ptrs.push_back(formatter =
- new filter_transactions(formatter,
- secondary_predicate));
-
- // sort_transactions will sort all the transactions it sees, based
- // on the `sort_order' value expression.
- if (! sort_string.empty()) {
- if (entry_sort)
- ptrs.push_back(formatter =
- new sort_entries(formatter, sort_string));
- else
- ptrs.push_back(formatter =
- new sort_transactions(formatter, sort_string));
- }
-
- // changed_value_transactions adds virtual transactions to the
- // list to account for changes in market value of commodities,
- // which otherwise would affect the running total unpredictably.
- if (show_revalued)
- ptrs.push_back(formatter =
- new changed_value_transactions(formatter,
- show_revalued_only));
-
- // collapse_transactions causes entries with multiple transactions
- // to appear as entries with a subtotaled transaction for each
- // commodity used.
- if (show_collapsed)
- ptrs.push_back(formatter = new collapse_transactions(formatter));
-
- // subtotal_transactions combines all the transactions it receives
- // into one subtotal entry, which has one transaction for each
- // commodity in each account.
- //
- // period_transactions is like subtotal_transactions, but it
- // subtotals according to time periods rather than totalling
- // everything.
- //
- // dow_transactions is like period_transactions, except that it
- // reports all the transactions that fall on each subsequent day
- // of the week.
- if (show_subtotal)
- ptrs.push_back(formatter =
- new subtotal_transactions(formatter, remember_components));
-
- if (days_of_the_week)
- ptrs.push_back(formatter =
- new dow_transactions(formatter, remember_components));
- else if (by_payee)
- ptrs.push_back(formatter =
- new by_payee_transactions(formatter, remember_components));
-
- // interval_transactions groups transactions together based on a
- // time period, such as weekly or monthly.
- if (! report_period.empty()) {
- ptrs.push_back(formatter =
- new interval_transactions(formatter, report_period,
- remember_components));
- ptrs.push_back(formatter = new sort_transactions(formatter, "d"));
- }
- }
-
- // invert_transactions inverts the value of the transactions it
- // receives.
- if (show_inverted)
- ptrs.push_back(formatter = new invert_transactions(formatter));
-
- // related_transactions will pass along all transactions related
- // to the transaction received. If `show_all_related' is true,
- // then all the entry's transactions are passed; meaning that if
- // one transaction of an entry is to be printed, all the
- // transaction for that entry will be printed.
- if (show_related)
- ptrs.push_back(formatter =
- new related_transactions(formatter,
- show_all_related));
-
- // This filter_transactions will only pass through transactions
- // matching the `predicate'.
- if (! predicate.empty())
- ptrs.push_back(formatter = new filter_transactions(formatter, predicate));
-
- // budget_transactions takes a set of transactions from a data
- // file and uses them to generate "budget transactions" which
- // balance against the reported transactions.
- //
- // forecast_transactions is a lot like budget_transactions, except
- // that it adds entries only for the future, and does not balance
- // them against anything but the future balance.
-
- if (budget_flags) {
- budget_transactions * handler
- = new budget_transactions(formatter, budget_flags);
- handler->add_period_entries(journal->period_entries);
- ptrs.push_back(formatter = handler);
-
- // Apply this before the budget handler, so that only matching
- // transactions are calculated toward the budget. The use of
- // filter_transactions above will further clean the results so
- // that no automated transactions that don't match the filter get
- // reported.
- if (! predicate.empty())
- ptrs.push_back(formatter = new filter_transactions(formatter, predicate));
- }
- else if (! forecast_limit.empty()) {
- forecast_transactions * handler
- = new forecast_transactions(formatter, forecast_limit);
- handler->add_period_entries(journal->period_entries);
- ptrs.push_back(formatter = handler);
-
- // See above, under budget_transactions.
- if (! predicate.empty())
- ptrs.push_back(formatter = new filter_transactions(formatter, predicate));
- }
-
- if (comm_as_payee)
- ptrs.push_back(formatter = new set_comm_as_payee(formatter));
- else if (code_as_payee)
- ptrs.push_back(formatter = new set_code_as_payee(formatter));
-
- return formatter;
-}
-
-} // namespace ledger
diff --git a/report.h b/report.h
deleted file mode 100644
index 377b9c57..00000000
--- a/report.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef _REPORT_H
-#define _REPORT_H
-
-#include "ledger.h"
-#include "timing.h"
-
-#include <iostream>
-#include <memory>
-#include <list>
-
-namespace ledger {
-
-class report_t
-{
- public:
- std::string output_file;
- std::string predicate;
- std::string secondary_predicate;
- std::string display_predicate;
- std::string report_period;
- std::string report_period_sort;
- std::string format_string;
- std::string sort_string;
- std::string amount_expr;
- std::string total_expr;
- std::string descend_expr;
- std::string forecast_limit;
- std::string reconcile_balance;
- std::string reconcile_date;
- std::string date_output_format;
-
- unsigned long budget_flags;
-
- int head_entries;
- int tail_entries;
-
- bool show_collapsed;
- bool show_subtotal;
- bool show_totals;
- bool show_related;
- bool show_all_related;
- bool show_inverted;
- bool show_empty;
- bool days_of_the_week;
- bool by_payee;
- bool comm_as_payee;
- bool code_as_payee;
- bool show_revalued;
- bool show_revalued_only;
- bool keep_price;
- bool keep_date;
- bool keep_tag;
- bool entry_sort;
- bool sort_all;
-
- report_t();
-
- void regexps_to_predicate(const std::string& command,
- std::list<std::string>::const_iterator begin,
- std::list<std::string>::const_iterator end,
- const bool account_regexp = false,
- const bool add_account_short_masks = false,
- const bool logical_and = true);
-
- void process_options(const std::string& command,
- strings_list::iterator arg,
- strings_list::iterator args_end);
-
- item_handler<transaction_t> *
- chain_xact_handlers(const std::string& command,
- item_handler<transaction_t> * base_formatter,
- journal_t * journal,
- account_t * master,
- std::list<item_handler<transaction_t> *>& ptrs);
-};
-
-} // namespace ledger
-
-#endif // _REPORT_H
diff --git a/sample.dat b/sample.dat
deleted file mode 100644
index 4a271d6f..00000000
--- a/sample.dat
+++ /dev/null
@@ -1,26 +0,0 @@
-= /^Expenses:Books/
- (Liabilities:Taxes) -0.10
-
-~ Monthly
- Assets:Bank:Checking $500.00
- Income:Salary
-
-2004/05/01 * Checking balance
- Assets:Bank:Checking $1,000.00
- Equity:Opening Balances
-
-2004/05/01 * Investment balance
- Assets:Brokerage 50 AAPL @ $30.00
- Equity:Opening Balances
-
-2004/05/14 * Pay day
- Assets:Bank:Checking $500.00
- Income:Salary
-
-2004/05/27 Book Store
- Expenses:Books $20.00
- Liabilities:MasterCard
-
-2004/05/27 (100) Credit card company
- Liabilities:MasterCard $20.00
- Assets:Bank:Checking
diff --git a/setup.py b/setup.py
deleted file mode 100755
index ad85633b..00000000
--- a/setup.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env python
-
-from distutils.core import setup, Extension
-
-import os
-
-defines = [('PYTHON_MODULE', 1)]
-libs = ["amounts", "boost_python", "gmp"]
-
-setup(name = "Amounts",
- version = "2.6.1",
- description = "Amounts and Commodities Library",
- author = "John Wiegley",
- author_email = "johnw@newartisans.com",
- url = "http://www.newartisans.com/johnw/",
- ext_modules = [
- Extension("amounts", [os.path.join(os.environ['SRCDIR'], "amounts.cc")],
- define_macros = [('PYTHON_MODULE', 1)],
- libraries = libs)])
diff --git a/src/account.cc b/src/account.cc
new file mode 100644
index 00000000..e6c7af56
--- /dev/null
+++ b/src/account.cc
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "account.h"
+#include "post.h"
+#include "xact.h"
+#include "interactive.h"
+
+namespace ledger {
+
+account_t::~account_t()
+{
+ TRACE_DTOR(account_t);
+
+ foreach (accounts_map::value_type& pair, accounts)
+ if (! pair.second->has_flags(ACCOUNT_TEMP))
+ checked_delete(pair.second);
+}
+
+account_t * account_t::find_account(const string& name,
+ const bool auto_create)
+{
+ accounts_map::const_iterator i = accounts.find(name);
+ if (i != accounts.end())
+ return (*i).second;
+
+ char buf[8192];
+
+ string::size_type sep = name.find(':');
+ assert(sep < 256|| sep == string::npos);
+
+ const char * first, * rest;
+ if (sep == string::npos) {
+ first = name.c_str();
+ rest = NULL;
+ } else {
+ std::strncpy(buf, name.c_str(), sep);
+ buf[sep] = '\0';
+
+ first = buf;
+ rest = name.c_str() + sep + 1;
+ }
+
+ account_t * account;
+
+ i = accounts.find(first);
+ if (i == accounts.end()) {
+ if (! auto_create)
+ return NULL;
+
+ account = new account_t(this, first);
+ std::pair<accounts_map::iterator, bool> result
+ = accounts.insert(accounts_map::value_type(first, account));
+ assert(result.second);
+ } else {
+ account = (*i).second;
+ }
+
+ if (rest)
+ account = account->find_account(rest, auto_create);
+
+ return account;
+}
+
+namespace {
+ account_t * find_account_re_(account_t * account, const mask_t& regexp)
+ {
+ if (regexp.match(account->fullname()))
+ return account;
+
+ foreach (accounts_map::value_type& pair, account->accounts)
+ if (account_t * a = find_account_re_(pair.second, regexp))
+ return a;
+
+ return NULL;
+ }
+}
+
+account_t * account_t::find_account_re(const string& regexp)
+{
+ return find_account_re_(this, mask_t(regexp));
+}
+
+bool account_t::remove_post(post_t * post)
+{
+ assert(! posts.empty());
+ posts.remove(post);
+ post->account = NULL;
+ return true;
+}
+
+string account_t::fullname() const
+{
+ if (! _fullname.empty()) {
+ return _fullname;
+ } else {
+ const account_t * first = this;
+ string fullname = name;
+
+ while (first->parent) {
+ first = first->parent;
+ if (! first->name.empty())
+ fullname = first->name + ":" + fullname;
+ }
+
+ _fullname = fullname;
+
+ return fullname;
+ }
+}
+
+string account_t::partial_name(bool flat) const
+{
+ string pname = name;
+
+ for (const account_t * acct = parent;
+ acct && acct->parent;
+ acct = acct->parent) {
+ if (! flat) {
+ std::size_t count = acct->children_with_flags(ACCOUNT_EXT_TO_DISPLAY);
+ assert(count > 0);
+ if (count > 1 || acct->has_xflags(ACCOUNT_EXT_TO_DISPLAY))
+ break;
+ }
+ pname = acct->name + ":" + pname;
+ }
+ return pname;
+}
+
+std::ostream& operator<<(std::ostream& out, const account_t& account)
+{
+ out << account.fullname();
+ return out;
+}
+
+namespace {
+ value_t get_partial_name(call_scope_t& scope)
+ {
+ in_context_t<account_t> env(scope, "&b");
+ return string_value(env->partial_name(env.has(0) ?
+ env.get<bool>(0) : false));
+ }
+
+ value_t get_account(account_t& account) { // this gets the name
+ return string_value(account.fullname());
+ }
+
+ value_t get_account_base(account_t& account) {
+ return string_value(account.name);
+ }
+
+ value_t get_amount(account_t& account) {
+ return SIMPLIFIED_VALUE_OR_ZERO(account.amount());
+ }
+
+ value_t get_total(account_t& account) {
+ return SIMPLIFIED_VALUE_OR_ZERO(account.total());
+ }
+
+ value_t get_subcount(account_t& account) {
+ return long(account.self_details().posts_count);
+ }
+
+ value_t get_count(account_t& account) {
+ return long(account.family_details().posts_count);
+ }
+
+ value_t get_depth(account_t& account) {
+ return long(account.depth);
+ }
+
+ value_t ignore(account_t&) {
+ return false;
+ }
+
+ value_t get_true(account_t&) {
+ return true;
+ }
+
+ value_t get_depth_spacer(account_t& account)
+ {
+ std::size_t depth = 0;
+ for (const account_t * acct = account.parent;
+ acct && acct->parent;
+ acct = acct->parent) {
+ std::size_t count = acct->children_with_flags(ACCOUNT_EXT_TO_DISPLAY);
+ assert(count > 0);
+ if (count > 1 || acct->has_xflags(ACCOUNT_EXT_TO_DISPLAY))
+ depth++;
+ }
+
+ std::ostringstream out;
+ for (std::size_t i = 0; i < depth; i++)
+ out << " ";
+
+ return string_value(out.str());
+ }
+
+ value_t get_latest_cleared(account_t& account)
+ {
+ return account.self_details().latest_cleared_post;
+ }
+
+ template <value_t (*Func)(account_t&)>
+ value_t get_wrapper(call_scope_t& scope) {
+ return (*Func)(find_scope<account_t>(scope));
+ }
+
+ value_t get_parent(account_t& account) {
+ return value_t(static_cast<scope_t *>(account.parent));
+ }
+}
+
+expr_t::ptr_op_t account_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
+{
+ if (kind != symbol_t::FUNCTION)
+ return NULL;
+
+ switch (name[0]) {
+ case 'a':
+ if (name[1] == '\0' || name == "amount")
+ return WRAP_FUNCTOR(get_wrapper<&get_amount>);
+ else if (name == "account")
+ return WRAP_FUNCTOR(get_wrapper<&get_account>);
+ else if (name == "account_base")
+ return WRAP_FUNCTOR(get_wrapper<&get_account_base>);
+ break;
+
+ case 'c':
+ if (name == "count")
+ return WRAP_FUNCTOR(get_wrapper<&get_count>);
+ break;
+
+ case 'd':
+ if (name == "depth")
+ return WRAP_FUNCTOR(get_wrapper<&get_depth>);
+ else if (name == "depth_spacer")
+ return WRAP_FUNCTOR(get_wrapper<&get_depth_spacer>);
+ break;
+
+ case 'i':
+ if (name == "is_account")
+ return WRAP_FUNCTOR(get_wrapper<&get_true>);
+ else if (name == "is_index")
+ return WRAP_FUNCTOR(get_wrapper<&get_subcount>);
+ break;
+
+ case 'l':
+ if (name == "latest_cleared")
+ return WRAP_FUNCTOR(get_wrapper<&get_latest_cleared>);
+ else if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_depth>);
+ break;
+
+ case 'n':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_subcount>);
+ break;
+
+ case 'p':
+ if (name == "partial_account")
+ return WRAP_FUNCTOR(get_partial_name);
+ else if (name == "parent")
+ return WRAP_FUNCTOR(get_wrapper<&get_parent>);
+ break;
+
+ case 's':
+ if (name == "subcount")
+ return WRAP_FUNCTOR(get_wrapper<&get_subcount>);
+ break;
+
+ case 't':
+ if (name == "total")
+ return WRAP_FUNCTOR(get_wrapper<&get_total>);
+ break;
+
+ case 'u':
+ if (name == "use_direct_amount")
+ return WRAP_FUNCTOR(get_wrapper<&ignore>);
+ break;
+
+ case 'N':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_count>);
+ break;
+
+ case 'O':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_total>);
+ break;
+ }
+
+ return NULL;
+}
+
+bool account_t::valid() const
+{
+ if (depth > 256) {
+ DEBUG("ledger.validate", "account_t: depth > 256");
+ return false;
+ }
+
+ foreach (const accounts_map::value_type& pair, accounts) {
+ if (this == pair.second) {
+ DEBUG("ledger.validate", "account_t: parent refers to itself!");
+ return false;
+ }
+
+ if (! pair.second->valid()) {
+ DEBUG("ledger.validate", "account_t: child not valid");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool account_t::children_with_xdata() const
+{
+ foreach (const accounts_map::value_type& pair, accounts)
+ if (pair.second->has_xdata() ||
+ pair.second->children_with_xdata())
+ return true;
+
+ return false;
+}
+
+std::size_t account_t::children_with_flags(xdata_t::flags_t flags) const
+{
+ std::size_t count = 0;
+ bool grandchildren_visited = false;
+
+ foreach (const accounts_map::value_type& pair, accounts)
+ if (pair.second->has_xflags(flags) ||
+ pair.second->children_with_flags(flags))
+ count++;
+
+ // Although no immediately children were visited, if any progeny at all were
+ // visited, it counts as one.
+ if (count == 0 && grandchildren_visited)
+ count = 1;
+
+ return count;
+}
+
+account_t::xdata_t::details_t&
+account_t::xdata_t::details_t::operator+=(const details_t& other)
+{
+ posts_count += other.posts_count;
+ posts_virtuals_count += other.posts_virtuals_count;
+ posts_cleared_count += other.posts_cleared_count;
+ posts_last_7_count += other.posts_last_7_count;
+ posts_last_30_count += other.posts_last_30_count;
+ posts_this_month_count += other.posts_this_month_count;
+
+ if (! is_valid(earliest_post) ||
+ (is_valid(other.earliest_post) &&
+ other.earliest_post < earliest_post))
+ earliest_post = other.earliest_post;
+ if (! is_valid(earliest_cleared_post) ||
+ (is_valid(other.earliest_cleared_post) &&
+ other.earliest_cleared_post < earliest_cleared_post))
+ earliest_cleared_post = other.earliest_cleared_post;
+
+ if (! is_valid(latest_post) ||
+ (is_valid(other.latest_post) &&
+ other.latest_post > latest_post))
+ latest_post = other.latest_post;
+ if (! is_valid(latest_cleared_post) ||
+ (is_valid(other.latest_cleared_post) &&
+ other.latest_cleared_post > latest_cleared_post))
+ latest_cleared_post = other.latest_cleared_post;
+
+ filenames.insert(other.filenames.begin(), other.filenames.end());
+ accounts_referenced.insert(other.accounts_referenced.begin(),
+ other.accounts_referenced.end());
+ payees_referenced.insert(other.payees_referenced.begin(),
+ other.payees_referenced.end());
+ return *this;
+}
+
+void account_t::clear_xdata()
+{
+ xdata_ = none;
+
+ foreach (accounts_map::value_type& pair, accounts)
+ if (! pair.second->has_flags(ACCOUNT_TEMP))
+ pair.second->clear_xdata();
+}
+
+value_t account_t::amount(const optional<expr_t&>& expr) const
+{
+ if (xdata_ && xdata_->has_flags(ACCOUNT_EXT_VISITED)) {
+ posts_list::const_iterator i;
+ if (xdata_->self_details.last_post)
+ i = *xdata_->self_details.last_post;
+ else
+ i = posts.begin();
+
+ for (; i != posts.end(); i++) {
+ if ((*i)->xdata().has_flags(POST_EXT_VISITED)) {
+ if (! (*i)->xdata().has_flags(POST_EXT_CONSIDERED)) {
+ (*i)->add_to_value(xdata_->self_details.total, expr);
+ (*i)->xdata().add_flags(POST_EXT_CONSIDERED);
+ }
+ }
+ xdata_->self_details.last_post = i;
+ }
+
+ if (xdata_->self_details.last_reported_post)
+ i = *xdata_->self_details.last_reported_post;
+ else
+ i = xdata_->reported_posts.begin();
+
+ for (; i != xdata_->reported_posts.end(); i++) {
+ if ((*i)->xdata().has_flags(POST_EXT_VISITED)) {
+ if (! (*i)->xdata().has_flags(POST_EXT_CONSIDERED)) {
+ (*i)->add_to_value(xdata_->self_details.total, expr);
+ (*i)->xdata().add_flags(POST_EXT_CONSIDERED);
+ }
+ }
+ xdata_->self_details.last_reported_post = i;
+ }
+
+ return xdata_->self_details.total;
+ } else {
+ return NULL_VALUE;
+ }
+}
+
+value_t account_t::total(const optional<expr_t&>& expr) const
+{
+ if (! (xdata_ && xdata_->family_details.calculated)) {
+ const_cast<account_t&>(*this).xdata().family_details.calculated = true;
+
+ value_t temp;
+ foreach (const accounts_map::value_type& pair, accounts) {
+ temp = pair.second->total(expr);
+ if (! temp.is_null())
+ add_or_set_value(xdata_->family_details.total, temp);
+ }
+
+ temp = amount(expr);
+ if (! temp.is_null())
+ add_or_set_value(xdata_->family_details.total, temp);
+ }
+ return xdata_->family_details.total;
+}
+
+const account_t::xdata_t::details_t&
+account_t::self_details(bool gather_all) const
+{
+ if (! (xdata_ && xdata_->self_details.gathered)) {
+ const_cast<account_t&>(*this).xdata().self_details.gathered = true;
+
+ foreach (const post_t * post, posts)
+ xdata_->self_details.update(const_cast<post_t&>(*post), gather_all);
+ }
+ return xdata_->self_details;
+}
+
+const account_t::xdata_t::details_t&
+account_t::family_details(bool gather_all) const
+{
+ if (! (xdata_ && xdata_->family_details.gathered)) {
+ const_cast<account_t&>(*this).xdata().family_details.gathered = true;
+
+ foreach (const accounts_map::value_type& pair, accounts)
+ xdata_->family_details += pair.second->family_details(gather_all);
+
+ xdata_->family_details += self_details(gather_all);
+ }
+ return xdata_->family_details;
+}
+
+void account_t::xdata_t::details_t::update(post_t& post,
+ bool gather_all)
+{
+ posts_count++;
+
+ if (post.has_flags(POST_VIRTUAL))
+ posts_virtuals_count++;
+
+ if (gather_all)
+ filenames.insert(post.pos->pathname);
+
+ date_t date = post.date();
+
+ if (date.year() == CURRENT_DATE().year() &&
+ date.month() == CURRENT_DATE().month())
+ posts_this_month_count++;
+
+ if ((CURRENT_DATE() - date).days() <= 30)
+ posts_last_30_count++;
+ if ((CURRENT_DATE() - date).days() <= 7)
+ posts_last_7_count++;
+
+ if (! is_valid(earliest_post) || post.date() < earliest_post)
+ earliest_post = post.date();
+ if (! is_valid(latest_post) || post.date() > latest_post)
+ latest_post = post.date();
+
+ if (post.state() == item_t::CLEARED) {
+ posts_cleared_count++;
+
+ if (! is_valid(earliest_cleared_post) ||
+ post.date() < earliest_cleared_post)
+ earliest_cleared_post = post.date();
+ if (! is_valid(latest_cleared_post) ||
+ post.date() > latest_cleared_post)
+ latest_cleared_post = post.date();
+ }
+
+ if (gather_all) {
+ accounts_referenced.insert(post.account->fullname());
+ payees_referenced.insert(post.xact->payee);
+ }
+}
+
+} // namespace ledger
diff --git a/src/account.h b/src/account.h
new file mode 100644
index 00000000..73cd35ac
--- /dev/null
+++ b/src/account.h
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup data
+ */
+
+/**
+ * @file account.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _ACCOUNT_H
+#define _ACCOUNT_H
+
+#include "scope.h"
+
+namespace ledger {
+
+class account_t;
+class xact_t;
+class post_t;
+
+typedef std::list<post_t *> posts_list;
+typedef std::map<const string, account_t *> accounts_map;
+
+class account_t : public supports_flags<>, public scope_t
+{
+#define ACCOUNT_NORMAL 0x00 // no flags at all, a basic account
+#define ACCOUNT_KNOWN 0x01
+#define ACCOUNT_TEMP 0x02 // account is a temporary object
+#define ACCOUNT_GENERATED 0x04 // account never actually existed
+
+public:
+ account_t * parent;
+ string name;
+ optional<string> note;
+ unsigned short depth;
+ accounts_map accounts;
+ posts_list posts;
+
+ mutable string _fullname;
+
+ account_t(account_t * _parent = NULL,
+ const string& _name = "",
+ const optional<string>& _note = none)
+ : supports_flags<>(), scope_t(), parent(_parent),
+ name(_name), note(_note),
+ depth(static_cast<unsigned short>(parent ? parent->depth + 1 : 0)) {
+ TRACE_CTOR(account_t, "account_t *, const string&, const string&");
+ }
+ account_t(const account_t& other)
+ : supports_flags<>(other.flags()), scope_t(),
+ parent(other.parent),
+ name(other.name),
+ note(other.note),
+ depth(other.depth),
+ accounts(other.accounts) {
+ TRACE_CTOR(account_t, "copy");
+ }
+ ~account_t();
+
+ operator string() const {
+ return fullname();
+ }
+ string fullname() const;
+ string partial_name(bool flat = false) const;
+
+ void add_account(account_t * acct) {
+ accounts.insert(accounts_map::value_type(acct->name, acct));
+ }
+ bool remove_account(account_t * acct) {
+ accounts_map::size_type n = accounts.erase(acct->name);
+ return n > 0;
+ }
+
+ account_t * find_account(const string& name, bool auto_create = true);
+ account_t * find_account_re(const string& regexp);
+
+ typedef transform_iterator<function<account_t *(accounts_map::value_type&)>,
+ accounts_map::iterator>
+ accounts_map_seconds_iterator;
+
+ accounts_map_seconds_iterator accounts_begin() {
+ return make_transform_iterator
+ (accounts.begin(), bind(&accounts_map::value_type::second, _1));
+ }
+ accounts_map_seconds_iterator accounts_end() {
+ return make_transform_iterator
+ (accounts.end(), bind(&accounts_map::value_type::second, _1));
+ }
+
+ void add_post(post_t * post) {
+ posts.push_back(post);
+ }
+ bool remove_post(post_t * post);
+
+ posts_list::iterator posts_begin() {
+ return posts.begin();
+ }
+ posts_list::iterator posts_end() {
+ return posts.end();
+ }
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
+
+ bool valid() const;
+
+ friend class journal_t;
+
+ struct xdata_t : public supports_flags<>
+ {
+#define ACCOUNT_EXT_SORT_CALC 0x01
+#define ACCOUNT_EXT_HAS_NON_VIRTUALS 0x02
+#define ACCOUNT_EXT_HAS_UNB_VIRTUALS 0x04
+#define ACCOUNT_EXT_AUTO_VIRTUALIZE 0x08
+#define ACCOUNT_EXT_VISITED 0x10
+#define ACCOUNT_EXT_MATCHING 0x20
+#define ACCOUNT_EXT_TO_DISPLAY 0x40
+#define ACCOUNT_EXT_DISPLAYED 0x80
+
+ struct details_t
+ {
+ value_t total;
+ bool calculated;
+ bool gathered;
+
+ std::size_t posts_count;
+ std::size_t posts_virtuals_count;
+ std::size_t posts_cleared_count;
+ std::size_t posts_last_7_count;
+ std::size_t posts_last_30_count;
+ std::size_t posts_this_month_count;
+
+ date_t earliest_post;
+ date_t earliest_cleared_post;
+ date_t latest_post;
+ date_t latest_cleared_post;
+
+ std::set<path> filenames;
+ std::set<string> accounts_referenced;
+ std::set<string> payees_referenced;
+
+ optional<posts_list::const_iterator> last_post;
+ optional<posts_list::const_iterator> last_reported_post;
+
+ details_t()
+ : calculated(false),
+ gathered(false),
+
+ posts_count(0),
+ posts_virtuals_count(0),
+ posts_cleared_count(0),
+ posts_last_7_count(0),
+ posts_last_30_count(0),
+ posts_this_month_count(0) {}
+
+ details_t& operator+=(const details_t& other);
+
+ void update(post_t& post, bool gather_all = false);
+ };
+
+ details_t self_details;
+ details_t family_details;
+ posts_list reported_posts;
+
+ std::list<sort_value_t> sort_values;
+
+ xdata_t() : supports_flags<>()
+ {
+ TRACE_CTOR(account_t::xdata_t, "");
+ }
+ xdata_t(const xdata_t& other)
+ : supports_flags<>(other.flags()),
+ self_details(other.self_details),
+ family_details(other.family_details),
+ sort_values(other.sort_values)
+ {
+ TRACE_CTOR(account_t::xdata_t, "copy");
+ }
+ ~xdata_t() throw() {
+ TRACE_DTOR(account_t::xdata_t);
+ }
+ };
+
+ // This variable holds optional "extended data" which is usually produced
+ // only during reporting, and only for the posting set being reported.
+ // It's a memory-saving measure to delay allocation until the last possible
+ // moment.
+ mutable optional<xdata_t> xdata_;
+
+ bool has_xdata() const {
+ return xdata_;
+ }
+ void clear_xdata();
+ xdata_t& xdata() {
+ if (! xdata_)
+ xdata_ = xdata_t();
+ return *xdata_;
+ }
+ const xdata_t& xdata() const {
+ assert(xdata_);
+ return *xdata_;
+ }
+
+ value_t amount(const optional<expr_t&>& expr = none) const;
+ value_t total(const optional<expr_t&>& expr = none) const;
+
+ const xdata_t::details_t& self_details(bool gather_all = true) const;
+ const xdata_t::details_t& family_details(bool gather_all = true) const;
+
+ bool has_xflags(xdata_t::flags_t flags) const {
+ return xdata_ && xdata_->has_flags(flags);
+ }
+ bool children_with_xdata() const;
+ std::size_t children_with_flags(xdata_t::flags_t flags) const;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<supports_flags<> >(*this);
+ ar & boost::serialization::base_object<scope_t>(*this);
+ ar & parent;
+ ar & name;
+ ar & note;
+ ar & depth;
+ ar & accounts;
+ ar & posts;
+ ar & _fullname;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+std::ostream& operator<<(std::ostream& out, const account_t& account);
+
+} // namespace ledger
+
+#endif // _ACCOUNT_H
diff --git a/src/accum.cc b/src/accum.cc
new file mode 100644
index 00000000..b918c76a
--- /dev/null
+++ b/src/accum.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "utils.h"
+
+namespace ledger {
+
+std::streamsize straccbuf::xsputn(const char * s, std::streamsize num)
+{
+ if (index == 0) {
+ // The first item received is the format string
+ str = std::string(s, num);
+ index++;
+ return num;
+ }
+ else {
+ std::ostringstream buf;
+
+ // Every item thereafter is an argument that substitutes for %# in the
+ // format string
+ bool matched = false;
+ for (const char * p = str.c_str(); *p; p++) {
+ if (*p == '%') {
+ const char * q = p + 1;
+ if (*q && *q != '%' && std::isdigit(*q) &&
+ std::string::size_type(*q - '0') == index) {
+ p++;
+ buf << std::string(s, num);
+ matched = true;
+ } else {
+ buf << *p;
+ }
+ } else {
+ buf << *p;
+ }
+ }
+ if (! matched)
+ buf << std::string(s, num);
+
+ str = buf.str();
+ index++;
+ return num;
+ }
+}
+
+} // namespace ledger
diff --git a/src/accum.h b/src/accum.h
new file mode 100644
index 00000000..878c2b7c
--- /dev/null
+++ b/src/accum.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup util
+ */
+
+/**
+ * @file accum.h
+ * @author John Wiegley
+ *
+ * @ingroup util
+ */
+#ifndef _ACCUM_H
+#define _ACCUM_H
+
+namespace ledger {
+
+class straccbuf : public std::streambuf
+{
+protected:
+ std::string str; // accumulator
+ std::string::size_type index;
+
+public:
+ straccbuf() : index(0) {}
+
+protected:
+ virtual std::streamsize xsputn(const char * s, std::streamsize num);
+
+ friend class straccstream;
+};
+
+class straccstream : public std::ostream
+{
+protected:
+ straccbuf buf;
+
+public:
+ straccstream() : std::ostream(0) {
+ rdbuf(&buf);
+ }
+
+ void clear() {
+ buf.str.clear();
+ buf.index = 0;
+ }
+
+ std::string str() const {
+ return buf.str;
+ }
+};
+
+#define ACCUM(obj) (static_cast<straccstream&>(obj).str())
+
+} // namespace ledger
+
+#endif // _ACCUM_H
diff --git a/src/amount.cc b/src/amount.cc
new file mode 100644
index 00000000..eddbca18
--- /dev/null
+++ b/src/amount.cc
@@ -0,0 +1,1278 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "amount.h"
+#include "commodity.h"
+#include "annotate.h"
+#include "pool.h"
+
+namespace ledger {
+
+bool amount_t::stream_fullstrings = false;
+
+#if !defined(THREADSAFE)
+// These global temporaries are pre-initialized for the sake of
+// efficiency, and are reused over and over again.
+static mpz_t temp;
+static mpq_t tempq;
+static mpfr_t tempf;
+static mpfr_t tempfb;
+#endif
+
+struct amount_t::bigint_t : public supports_flags<>
+{
+#define BIGINT_BULK_ALLOC 0x01
+#define BIGINT_KEEP_PREC 0x02
+
+ mpq_t val;
+ precision_t prec;
+ uint_least32_t refc;
+
+#define MP(bigint) ((bigint)->val)
+
+ bigint_t() : prec(0), refc(1) {
+ TRACE_CTOR(bigint_t, "");
+ mpq_init(val);
+ }
+ bigint_t(const bigint_t& other)
+ : supports_flags<>(static_cast<uint_least8_t>
+ (other.flags() & ~BIGINT_BULK_ALLOC)),
+ prec(other.prec), refc(1) {
+ TRACE_CTOR(bigint_t, "copy");
+ mpq_init(val);
+ mpq_set(val, other.val);
+ }
+ ~bigint_t() {
+ TRACE_DTOR(bigint_t);
+ assert(refc == 0);
+ mpq_clear(val);
+ }
+
+ bool valid() const {
+ if (prec > 1024) {
+ DEBUG("ledger.validate", "amount_t::bigint_t: prec > 1024");
+ return false;
+ }
+ if (flags() & ~(BIGINT_BULK_ALLOC | BIGINT_KEEP_PREC)) {
+ DEBUG("ledger.validate",
+ "amount_t::bigint_t: flags() & ~(BULK_ALLOC | KEEP_PREC)");
+ return false;
+ }
+ return true;
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */)
+ {
+ ar & boost::serialization::base_object<supports_flags<> >(*this);
+ ar & val;
+ ar & prec;
+ ar & refc;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+bool amount_t::is_initialized = false;
+
+namespace {
+ void stream_out_mpq(std::ostream& out,
+ mpq_t quant,
+ amount_t::precision_t prec,
+ int zeros_prec = -1,
+ const optional<commodity_t&>& comm = none)
+ {
+ char * buf = NULL;
+ try {
+ IF_DEBUG("amount.convert") {
+ char * tbuf = mpq_get_str(NULL, 10, quant);
+ DEBUG("amount.convert", "Rational to convert = " << tbuf);
+ std::free(tbuf);
+ }
+
+ // Convert the rational number to a floating-point, extending the
+ // floating-point to a large enough size to get a precise answer.
+ const std::size_t bits = (mpz_sizeinbase(mpq_numref(quant), 2) +
+ mpz_sizeinbase(mpq_denref(quant), 2));
+ mpfr_set_prec(tempfb, bits + amount_t::extend_by_digits*8);
+ mpfr_set_q(tempfb, quant, GMP_RNDN);
+
+ mpfr_asprintf(&buf, "%.*Rf", prec, tempfb);
+ DEBUG("amount.convert",
+ "mpfr_print = " << buf << " (precision " << prec << ")");
+
+ if (zeros_prec >= 0) {
+ string::size_type index = std::strlen(buf);
+ string::size_type point = 0;
+ for (string::size_type i = 0; i < index; i++) {
+ if (buf[i] == '.') {
+ point = i;
+ break;
+ }
+ }
+ if (point > 0) {
+ while (--index >= (point + 1 + zeros_prec) && buf[index] == '0')
+ buf[index] = '\0';
+ if (index >= (point + zeros_prec) && buf[index] == '.')
+ buf[index] = '\0';
+ }
+ }
+
+ if (comm) {
+ int integer_digits = 0;
+ if (comm && comm->has_flags(COMMODITY_STYLE_THOUSANDS)) {
+ // Count the number of integer digits
+ for (const char * p = buf; *p; p++) {
+ if (*p == '.')
+ break;
+ else if (*p != '-')
+ integer_digits++;
+ }
+ }
+
+ for (const char * p = buf; *p; p++) {
+ if (*p == '.') {
+ if (commodity_t::european_by_default ||
+ (comm && comm->has_flags(COMMODITY_STYLE_EUROPEAN)))
+ out << ',';
+ else
+ out << *p;
+ assert(integer_digits <= 3);
+ }
+ else if (*p == '-') {
+ out << *p;
+ }
+ else {
+ out << *p;
+
+ if (integer_digits > 3 && --integer_digits % 3 == 0) {
+ if (commodity_t::european_by_default ||
+ (comm && comm->has_flags(COMMODITY_STYLE_EUROPEAN)))
+ out << '.';
+ else
+ out << ',';
+ }
+ }
+ }
+ } else {
+ out << buf;
+ }
+ }
+ catch (...) {
+ if (buf != NULL)
+ mpfr_free_str(buf);
+ throw;
+ }
+ if (buf != NULL)
+ mpfr_free_str(buf);
+ }
+}
+
+void amount_t::initialize()
+{
+ if (! is_initialized) {
+ mpz_init(temp);
+ mpq_init(tempq);
+ mpfr_init(tempf);
+ mpfr_init(tempfb);
+
+ commodity_pool_t::current_pool.reset(new commodity_pool_t);
+
+ // Add time commodity conversions, so that timelog's may be parsed
+ // in terms of seconds, but reported as minutes or hours.
+ if (commodity_t * commodity = commodity_pool_t::current_pool->create("s"))
+ commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
+ else
+ assert(false);
+
+ // Add a "percentile" commodity
+ if (commodity_t * commodity = commodity_pool_t::current_pool->create("%"))
+ commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
+ else
+ assert(false);
+
+ is_initialized = true;
+ }
+}
+
+void amount_t::shutdown()
+{
+ if (is_initialized) {
+ mpz_clear(temp);
+ mpq_clear(tempq);
+ mpfr_clear(tempf);
+ mpfr_clear(tempfb);
+
+ commodity_pool_t::current_pool.reset();
+
+ is_initialized = false;
+ }
+}
+
+void amount_t::_copy(const amount_t& amt)
+{
+ VERIFY(amt.valid());
+
+ if (quantity != amt.quantity) {
+ if (quantity)
+ _release();
+
+ // Never maintain a pointer into a bulk allocation pool; such
+ // pointers are not guaranteed to remain.
+ if (amt.quantity->has_flags(BIGINT_BULK_ALLOC)) {
+ quantity = new bigint_t(*amt.quantity);
+ } else {
+ quantity = amt.quantity;
+ DEBUG("amounts.refs",
+ quantity << " refc++, now " << (quantity->refc + 1));
+ quantity->refc++;
+ }
+ }
+ commodity_ = amt.commodity_;
+
+ VERIFY(valid());
+}
+
+void amount_t::_dup()
+{
+ VERIFY(valid());
+
+ if (quantity->refc > 1) {
+ bigint_t * q = new bigint_t(*quantity);
+ _release();
+ quantity = q;
+ }
+
+ VERIFY(valid());
+}
+
+void amount_t::_clear()
+{
+ if (quantity) {
+ _release();
+ quantity = NULL;
+ commodity_ = NULL;
+ } else {
+ assert(! commodity_);
+ }
+}
+
+void amount_t::_release()
+{
+ VERIFY(valid());
+
+ DEBUG("amounts.refs", quantity << " refc--, now " << (quantity->refc - 1));
+
+ if (--quantity->refc == 0) {
+ if (quantity->has_flags(BIGINT_BULK_ALLOC))
+ quantity->~bigint_t();
+ else
+ checked_delete(quantity);
+ quantity = NULL;
+ commodity_ = NULL;
+ }
+
+ VERIFY(valid());
+}
+
+
+amount_t::amount_t(const double val) : commodity_(NULL)
+{
+ TRACE_CTOR(amount_t, "const double");
+ quantity = new bigint_t;
+ mpq_set_d(MP(quantity), val);
+ quantity->prec = extend_by_digits; // an approximation
+}
+
+amount_t::amount_t(const unsigned long val) : commodity_(NULL)
+{
+ TRACE_CTOR(amount_t, "const unsigned long");
+ quantity = new bigint_t;
+ mpq_set_ui(MP(quantity), val, 1);
+}
+
+amount_t::amount_t(const long val) : commodity_(NULL)
+{
+ TRACE_CTOR(amount_t, "const long");
+ quantity = new bigint_t;
+ mpq_set_si(MP(quantity), val, 1);
+}
+
+
+amount_t& amount_t::operator=(const amount_t& amt)
+{
+ if (this != &amt) {
+ if (amt.quantity)
+ _copy(amt);
+ else if (quantity)
+ _clear();
+ }
+ return *this;
+}
+
+
+int amount_t::compare(const amount_t& amt) const
+{
+ VERIFY(amt.valid());
+
+ if (! quantity || ! amt.quantity) {
+ if (quantity)
+ throw_(amount_error, _("Cannot compare an amount to an uninitialized amount"));
+ else if (amt.quantity)
+ throw_(amount_error, _("Cannot compare an uninitialized amount to an amount"));
+ else
+ throw_(amount_error, _("Cannot compare two uninitialized amounts"));
+ }
+
+ if (has_commodity() && amt.has_commodity() &&
+ commodity() != amt.commodity())
+ throw_(amount_error,
+ _("Cannot compare amounts with different commodities: %1 and %2")
+ << commodity().symbol() << amt.commodity().symbol());
+
+ return mpq_cmp(MP(quantity), MP(amt.quantity));
+}
+
+bool amount_t::operator==(const amount_t& amt) const
+{
+ if ((quantity && ! amt.quantity) || (! quantity && amt.quantity))
+ return false;
+ else if (! quantity && ! amt.quantity)
+ return true;
+ else if (commodity() != amt.commodity())
+ return false;
+
+ return mpq_equal(MP(quantity), MP(amt.quantity));
+}
+
+
+amount_t& amount_t::operator+=(const amount_t& amt)
+{
+ VERIFY(amt.valid());
+
+ if (! quantity || ! amt.quantity) {
+ if (quantity)
+ throw_(amount_error, _("Cannot add an uninitialized amount to an amount"));
+ else if (amt.quantity)
+ throw_(amount_error, _("Cannot add an amount to an uninitialized amount"));
+ else
+ throw_(amount_error, _("Cannot add two uninitialized amounts"));
+ }
+
+ if (has_commodity() && amt.has_commodity() &&
+ commodity() != amt.commodity())
+ throw_(amount_error,
+ _("Adding amounts with different commodities: %1 != %2")
+ << (has_commodity() ? commodity().symbol() : _("NONE"))
+ << (amt.has_commodity() ? amt.commodity().symbol() : _("NONE")));
+
+ _dup();
+
+ mpq_add(MP(quantity), MP(quantity), MP(amt.quantity));
+
+ if (has_commodity() == amt.has_commodity())
+ if (quantity->prec < amt.quantity->prec)
+ quantity->prec = amt.quantity->prec;
+
+ return *this;
+}
+
+amount_t& amount_t::operator-=(const amount_t& amt)
+{
+ VERIFY(amt.valid());
+
+ if (! quantity || ! amt.quantity) {
+ if (quantity)
+ throw_(amount_error, _("Cannot subtract an amount from an uninitialized amount"));
+ else if (amt.quantity)
+ throw_(amount_error, _("Cannot subtract an uninitialized amount from an amount"));
+ else
+ throw_(amount_error, _("Cannot subtract two uninitialized amounts"));
+ }
+
+ if (has_commodity() && amt.has_commodity() &&
+ commodity() != amt.commodity())
+ throw_(amount_error,
+ _("Subtracting amounts with different commodities: %1 != %2")
+ << (has_commodity() ? commodity().symbol() : _("NONE"))
+ << (amt.has_commodity() ? amt.commodity().symbol() : _("NONE")));
+
+ _dup();
+
+ mpq_sub(MP(quantity), MP(quantity), MP(amt.quantity));
+
+ if (has_commodity() == amt.has_commodity())
+ if (quantity->prec < amt.quantity->prec)
+ quantity->prec = amt.quantity->prec;
+
+ return *this;
+}
+
+amount_t& amount_t::operator*=(const amount_t& amt)
+{
+ VERIFY(amt.valid());
+
+ if (! quantity || ! amt.quantity) {
+ if (quantity)
+ throw_(amount_error, _("Cannot multiply an amount by an uninitialized amount"));
+ else if (amt.quantity)
+ throw_(amount_error, _("Cannot multiply an uninitialized amount by an amount"));
+ else
+ throw_(amount_error, _("Cannot multiply two uninitialized amounts"));
+ }
+
+ _dup();
+
+ mpq_mul(MP(quantity), MP(quantity), MP(amt.quantity));
+ quantity->prec =
+ static_cast<precision_t>(quantity->prec + amt.quantity->prec);
+
+ if (! has_commodity())
+ commodity_ = amt.commodity_;
+
+ if (has_commodity() && ! keep_precision()) {
+ precision_t comm_prec = commodity().precision();
+ if (quantity->prec > comm_prec + extend_by_digits)
+ quantity->prec = static_cast<precision_t>(comm_prec + extend_by_digits);
+ }
+
+ return *this;
+}
+
+amount_t& amount_t::operator/=(const amount_t& amt)
+{
+ VERIFY(amt.valid());
+
+ if (! quantity || ! amt.quantity) {
+ if (quantity)
+ throw_(amount_error, _("Cannot divide an amount by an uninitialized amount"));
+ else if (amt.quantity)
+ throw_(amount_error, _("Cannot divide an uninitialized amount by an amount"));
+ else
+ throw_(amount_error, _("Cannot divide two uninitialized amounts"));
+ }
+
+ if (! amt)
+ throw_(amount_error, _("Divide by zero"));
+
+ _dup();
+
+ // Increase the value's precision, to capture fractional parts after
+ // the divide. Round up in the last position.
+
+ mpq_div(MP(quantity), MP(quantity), MP(amt.quantity));
+ quantity->prec =
+ static_cast<precision_t>(quantity->prec + amt.quantity->prec +
+ extend_by_digits);
+
+ if (! has_commodity())
+ commodity_ = amt.commodity_;
+
+ // If this amount has a commodity, and we're not dealing with plain
+ // numbers, or internal numbers (which keep full precision at all
+ // times), then round the number to within the commodity's precision
+ // plus six places.
+
+ if (has_commodity() && ! keep_precision()) {
+ precision_t comm_prec = commodity().precision();
+ if (quantity->prec > comm_prec + extend_by_digits)
+ quantity->prec = static_cast<precision_t>(comm_prec + extend_by_digits);
+ }
+
+ return *this;
+}
+
+amount_t::precision_t amount_t::precision() const
+{
+ if (! quantity)
+ throw_(amount_error,
+ _("Cannot determine precision of an uninitialized amount"));
+
+ return quantity->prec;
+}
+
+bool amount_t::keep_precision() const
+{
+ if (! quantity)
+ throw_(amount_error,
+ _("Cannot determine if precision of an uninitialized amount is kept"));
+
+ return quantity->has_flags(BIGINT_KEEP_PREC);
+}
+
+void amount_t::set_keep_precision(const bool keep) const
+{
+ if (! quantity)
+ throw_(amount_error,
+ _("Cannot set whether to keep the precision of an uninitialized amount"));
+
+ if (keep)
+ quantity->add_flags(BIGINT_KEEP_PREC);
+ else
+ quantity->drop_flags(BIGINT_KEEP_PREC);
+}
+
+amount_t::precision_t amount_t::display_precision() const
+{
+ if (! quantity)
+ throw_(amount_error,
+ _("Cannot determine display precision of an uninitialized amount"));
+
+ commodity_t& comm(commodity());
+
+ if (! comm || keep_precision())
+ return quantity->prec;
+ else if (comm.precision() != quantity->prec)
+ return comm.precision();
+ else
+ return quantity->prec;
+}
+
+void amount_t::in_place_negate()
+{
+ if (quantity) {
+ _dup();
+ mpq_neg(MP(quantity), MP(quantity));
+ } else {
+ throw_(amount_error, _("Cannot negate an uninitialized amount"));
+ }
+}
+
+amount_t amount_t::inverted() const
+{
+ if (! quantity)
+ throw_(amount_error, _("Cannot invert an uninitialized amount"));
+
+ amount_t t(*this);
+ t._dup();
+ mpq_inv(MP(t.quantity), MP(t.quantity));
+
+ return t;
+}
+
+void amount_t::in_place_round()
+{
+ if (! quantity)
+ throw_(amount_error, _("Cannot set rounding for an uninitialized amount"));
+ else if (! keep_precision())
+ return;
+
+ _dup();
+ set_keep_precision(false);
+}
+
+void amount_t::in_place_floor()
+{
+ if (! quantity)
+ throw_(amount_error, _("Cannot floor an uninitialized amount"));
+
+ _dup();
+
+ std::ostringstream out;
+ stream_out_mpq(out, MP(quantity), 0);
+
+ mpq_set_str(MP(quantity), out.str().c_str(), 10);
+}
+
+void amount_t::in_place_unround()
+{
+ if (! quantity)
+ throw_(amount_error, _("Cannot unround an uninitialized amount"));
+ else if (keep_precision())
+ return;
+
+ _dup();
+
+ DEBUG("amount.unround", "Unrounding " << *this);
+ set_keep_precision(true);
+ DEBUG("amount.unround", "Unrounded = " << *this);
+}
+
+void amount_t::in_place_reduce()
+{
+ if (! quantity)
+ throw_(amount_error, _("Cannot reduce an uninitialized amount"));
+
+ while (commodity_ && commodity().smaller()) {
+ *this *= commodity().smaller()->number();
+ commodity_ = commodity().smaller()->commodity_;
+ }
+}
+
+void amount_t::in_place_unreduce()
+{
+ if (! quantity)
+ throw_(amount_error, _("Cannot unreduce an uninitialized amount"));
+
+ amount_t temp = *this;
+ commodity_t * comm = commodity_;
+ bool shifted = false;
+
+ while (comm && comm->larger()) {
+ amount_t next_temp = temp / comm->larger()->number();
+ if (next_temp.abs() < amount_t(1L))
+ break;
+ temp = next_temp;
+ comm = comm->larger()->commodity_;
+ shifted = true;
+ }
+
+ if (shifted) {
+ *this = temp;
+ commodity_ = comm;
+ }
+}
+
+optional<amount_t>
+amount_t::value(const bool primary_only,
+ const optional<datetime_t>& moment,
+ const optional<commodity_t&>& in_terms_of) const
+{
+ if (quantity) {
+#if defined(DEBUG_ON)
+ DEBUG("commodity.prices.find",
+ "amount_t::value of " << commodity().symbol());
+ if (moment)
+ DEBUG("commodity.prices.find",
+ "amount_t::value: moment = " << *moment);
+ if (in_terms_of)
+ DEBUG("commodity.prices.find",
+ "amount_t::value: in_terms_of = " << in_terms_of->symbol());
+#endif
+ if (has_commodity() &&
+ (! primary_only || ! commodity().has_flags(COMMODITY_PRIMARY))) {
+ if (in_terms_of && commodity() == *in_terms_of) {
+ return *this;
+ }
+ else if (has_annotation() && annotation().price &&
+ annotation().has_flags(ANNOTATION_PRICE_FIXATED)) {
+ return (*annotation().price * number()).rounded();
+ }
+ else {
+ optional<price_point_t> point =
+ commodity().find_price(in_terms_of, moment);
+
+ // Whether a price was found or not, check whether we should attempt
+ // to download a price from the Internet. This is done if (a) no
+ // price was found, or (b) the price is "stale" according to the
+ // setting of --price-exp.
+ point = commodity().check_for_updated_price(point, moment, in_terms_of);
+ if (point)
+ return (point->price * number()).rounded();
+ }
+ }
+ } else {
+ throw_(amount_error,
+ _("Cannot determine value of an uninitialized amount"));
+ }
+ return none;
+}
+
+amount_t amount_t::price() const
+{
+ if (has_annotation() && annotation().price) {
+ amount_t temp(*annotation().price);
+ temp *= *this;
+ DEBUG("amount.price", "Returning price of " << *this << " = " << temp);
+ return temp;
+ }
+ return *this;
+}
+
+
+int amount_t::sign() const
+{
+ if (! quantity)
+ throw_(amount_error, _("Cannot determine sign of an uninitialized amount"));
+
+ return mpq_sgn(MP(quantity));
+}
+
+bool amount_t::is_zero() const
+{
+ if (! quantity)
+ throw_(amount_error, _("Cannot determine if an uninitialized amount is zero"));
+
+ if (has_commodity()) {
+ if (keep_precision() || quantity->prec <= commodity().precision()) {
+ return is_realzero();
+ }
+ else if (is_realzero()) {
+ return true;
+ }
+ else if (mpz_cmp(mpq_numref(MP(quantity)),
+ mpq_denref(MP(quantity))) > 0) {
+ DEBUG("amount.is_zero", "Numerator is larger than the denominator");
+ return false;
+ }
+ else {
+ DEBUG("amount.is_zero", "We have to print the number to check for zero");
+
+ std::ostringstream out;
+ stream_out_mpq(out, MP(quantity), commodity().precision());
+
+ string output = out.str();
+ if (! output.empty()) {
+ for (const char * p = output.c_str(); *p; p++)
+ if (*p != '0' && *p != '.' && *p != '-')
+ return false;
+ }
+ return true;
+ }
+ }
+ return is_realzero();
+}
+
+
+double amount_t::to_double() const
+{
+ if (! quantity)
+ throw_(amount_error, _("Cannot convert an uninitialized amount to a double"));
+
+ mpfr_set_q(tempf, MP(quantity), GMP_RNDN);
+ return mpfr_get_d(tempf, GMP_RNDN);
+}
+
+long amount_t::to_long() const
+{
+ if (! quantity)
+ throw_(amount_error, _("Cannot convert an uninitialized amount to a long"));
+
+ mpfr_set_q(tempf, MP(quantity), GMP_RNDN);
+ return mpfr_get_si(tempf, GMP_RNDN);
+}
+
+bool amount_t::fits_in_long() const
+{
+ mpfr_set_q(tempf, MP(quantity), GMP_RNDN);
+ return mpfr_fits_slong_p(tempf, GMP_RNDN);
+}
+
+commodity_t& amount_t::commodity() const
+{
+ return (has_commodity() ?
+ *commodity_ : *commodity_pool_t::current_pool->null_commodity);
+}
+
+bool amount_t::has_commodity() const
+{
+ return commodity_ && commodity_ != commodity_->pool().null_commodity;
+}
+
+void amount_t::annotate(const annotation_t& details)
+{
+ commodity_t * this_base;
+ annotated_commodity_t * this_ann = NULL;
+
+ if (! quantity)
+ throw_(amount_error, _("Cannot annotate the commodity of an uninitialized amount"));
+ else if (! has_commodity())
+ return; // ignore attempt to annotate a "bare commodity
+
+ if (commodity().has_annotation()) {
+ this_ann = &as_annotated_commodity(commodity());
+ this_base = &this_ann->referent();
+ } else {
+ this_base = &commodity();
+ }
+ assert(this_base);
+
+ DEBUG("amounts.commodities", "Annotating commodity for amount "
+ << *this << std::endl << details);
+
+ if (commodity_t * ann_comm =
+ this_base->pool().find_or_create(*this_base, details))
+ set_commodity(*ann_comm);
+#ifdef ASSERTS_ON
+ else
+ assert(false);
+#endif
+
+ DEBUG("amounts.commodities", "Annotated amount is " << *this);
+}
+
+bool amount_t::has_annotation() const
+{
+ if (! quantity)
+ throw_(amount_error,
+ _("Cannot determine if an uninitialized amount's commodity is annotated"));
+
+ assert(! has_commodity() || ! commodity().has_annotation() ||
+ as_annotated_commodity(commodity()).details);
+ return has_commodity() && commodity().has_annotation();
+}
+
+annotation_t& amount_t::annotation()
+{
+ if (! quantity)
+ throw_(amount_error,
+ _("Cannot return commodity annotation details of an uninitialized amount"));
+
+ if (! commodity().has_annotation())
+ throw_(amount_error,
+ _("Request for annotation details from an unannotated amount"));
+
+ annotated_commodity_t& ann_comm(as_annotated_commodity(commodity()));
+ return ann_comm.details;
+}
+
+amount_t amount_t::strip_annotations(const keep_details_t& what_to_keep) const
+{
+ if (! quantity)
+ throw_(amount_error,
+ _("Cannot strip commodity annotations from an uninitialized amount"));
+
+ if (! what_to_keep.keep_all(commodity())) {
+ amount_t t(*this);
+ t.set_commodity(commodity().strip_annotations(what_to_keep));
+ return t;
+ }
+ return *this;
+}
+
+
+namespace {
+ void parse_quantity(std::istream& in, string& value)
+ {
+ char buf[256];
+ char c = peek_next_nonws(in);
+ READ_INTO(in, buf, 255, c,
+ std::isdigit(c) || c == '-' || c == '.' || c == ',');
+
+ string::size_type len = std::strlen(buf);
+ while (len > 0 && ! std::isdigit(buf[len - 1])) {
+ buf[--len] = '\0';
+ in.unget();
+ }
+
+ value = buf;
+ }
+}
+
+bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
+{
+ // The possible syntax for an amount is:
+ //
+ // [-]NUM[ ]SYM [@ AMOUNT]
+ // SYM[ ][-]NUM [@ AMOUNT]
+
+ string symbol;
+ string quant;
+ annotation_t details;
+ bool negative = false;
+
+ commodity_t::flags_t comm_flags = COMMODITY_STYLE_DEFAULTS;
+
+ char c = peek_next_nonws(in);
+ if (c == '-') {
+ negative = true;
+ in.get(c);
+ c = peek_next_nonws(in);
+ }
+
+ char n;
+ if (std::isdigit(c)) {
+ parse_quantity(in, quant);
+
+ if (! in.eof() && ((n = static_cast<char>(in.peek())) != '\n')) {
+ if (std::isspace(n))
+ comm_flags |= COMMODITY_STYLE_SEPARATED;
+
+ commodity_t::parse_symbol(in, symbol);
+
+ if (! symbol.empty())
+ comm_flags |= COMMODITY_STYLE_SUFFIXED;
+
+ if (! in.eof() && ((n = static_cast<char>(in.peek())) != '\n'))
+ details.parse(in);
+ }
+ } else {
+ commodity_t::parse_symbol(in, symbol);
+
+ if (! in.eof() && ((n = static_cast<char>(in.peek())) != '\n')) {
+ if (std::isspace(static_cast<char>(in.peek())))
+ comm_flags |= COMMODITY_STYLE_SEPARATED;
+
+ parse_quantity(in, quant);
+
+ if (! quant.empty() && ! in.eof() &&
+ ((n = static_cast<char>(in.peek())) != '\n'))
+ details.parse(in);
+ }
+ }
+
+ if (quant.empty()) {
+ if (flags.has_flags(PARSE_SOFT_FAIL))
+ return false;
+ else
+ throw_(amount_error, _("No quantity specified for amount"));
+ }
+
+ // Allocate memory for the amount's quantity value. We have to
+ // monitor the allocation in an auto_ptr because this function gets
+ // called sometimes from amount_t's constructor; and if there is an
+ // exeception thrown by any of the function calls after this point,
+ // the destructor will never be called and the memory never freed.
+
+ std::auto_ptr<bigint_t> new_quantity;
+
+ if (quantity) {
+ if (quantity->refc > 1)
+ _release();
+ else
+ new_quantity.reset(quantity);
+ quantity = NULL;
+ }
+
+ if (! new_quantity.get())
+ new_quantity.reset(new bigint_t);
+
+ // No one is holding a reference to this now.
+ new_quantity->refc--;
+
+ // Create the commodity if has not already been seen, and update the
+ // precision if something greater was used for the quantity.
+
+ bool newly_created = false;
+
+ if (symbol.empty()) {
+ commodity_ = NULL;
+ } else {
+ commodity_ = commodity_pool_t::current_pool->find(symbol);
+ if (! commodity_) {
+ commodity_ = commodity_pool_t::current_pool->create(symbol);
+ newly_created = true;
+ }
+ assert(commodity_);
+
+ if (details)
+ commodity_ =
+ commodity_pool_t::current_pool->find_or_create(*commodity_, details);
+ }
+
+ // Quickly scan through and verify the correctness of the amount's use of
+ // punctuation.
+
+ precision_t decimal_offset = 0;
+ string::size_type string_index = quant.length();
+ string::size_type last_comma = string::npos;
+ string::size_type last_period = string::npos;
+
+ bool no_more_commas = false;
+ bool no_more_periods = false;
+ bool european_style = (commodity_t::european_by_default ||
+ commodity().has_flags(COMMODITY_STYLE_EUROPEAN));
+
+ new_quantity->prec = 0;
+
+ BOOST_REVERSE_FOREACH (const char& ch, quant) {
+ string_index--;
+
+ if (ch == '.') {
+ if (no_more_periods)
+ throw_(amount_error, _("Too many periods in amount"));
+
+ if (european_style) {
+ if (decimal_offset % 3 != 0)
+ throw_(amount_error, _("Incorrect use of european-style period"));
+ comm_flags |= COMMODITY_STYLE_THOUSANDS;
+ no_more_commas = true;
+ } else {
+ if (last_comma != string::npos) {
+ european_style = true;
+ if (decimal_offset % 3 != 0)
+ throw_(amount_error, _("Incorrect use of european-style period"));
+ } else {
+ no_more_periods = true;
+ new_quantity->prec = decimal_offset;
+ decimal_offset = 0;
+ }
+ }
+
+ if (last_period == string::npos)
+ last_period = string_index;
+ }
+ else if (ch == ',') {
+ if (no_more_commas)
+ throw_(amount_error, _("Too many commas in amount"));
+
+ if (european_style) {
+ if (last_period != string::npos) {
+ throw_(amount_error, _("Incorrect use of european-style comma"));
+ } else {
+ no_more_commas = true;
+ new_quantity->prec = decimal_offset;
+ decimal_offset = 0;
+ }
+ } else {
+ if (decimal_offset % 3 != 0) {
+ if (last_comma != string::npos ||
+ last_period != string::npos) {
+ throw_(amount_error, _("Incorrect use of American-style comma"));
+ } else {
+ european_style = true;
+ no_more_commas = true;
+ new_quantity->prec = decimal_offset;
+ decimal_offset = 0;
+ }
+ } else {
+ comm_flags |= COMMODITY_STYLE_THOUSANDS;
+ no_more_periods = true;
+ }
+ }
+
+ if (last_comma == string::npos)
+ last_comma = string_index;
+ }
+ else {
+ decimal_offset++;
+ }
+ }
+
+ if (european_style)
+ comm_flags |= COMMODITY_STYLE_EUROPEAN;
+
+ if (flags.has_flags(PARSE_NO_MIGRATE)) {
+ // Can't call set_keep_precision here, because it assumes that `quantity'
+ // is non-NULL.
+ new_quantity->add_flags(BIGINT_KEEP_PREC);
+ }
+ else if (commodity_) {
+ commodity().add_flags(comm_flags);
+
+ if (new_quantity->prec > commodity().precision())
+ commodity().set_precision(new_quantity->prec);
+ }
+
+ // Now we have the final number. Remove commas and periods, if necessary.
+
+ if (last_comma != string::npos || last_period != string::npos) {
+ string::size_type len = quant.length();
+ scoped_array<char> buf(new char[len + 1]);
+ const char * p = quant.c_str();
+ char * t = buf.get();
+
+ while (*p) {
+ if (*p == ',' || *p == '.')
+ p++;
+ *t++ = *p++;
+ }
+ *t = '\0';
+
+ mpq_set_str(MP(new_quantity.get()), buf.get(), 10);
+ mpz_ui_pow_ui(temp, 10, new_quantity->prec);
+ mpq_set_z(tempq, temp);
+ mpq_div(MP(new_quantity.get()), MP(new_quantity.get()), tempq);
+
+ IF_DEBUG("amount.parse") {
+ char * buf = mpq_get_str(NULL, 10, MP(new_quantity.get()));
+ DEBUG("amount.parse", "Rational parsed = " << buf);
+ std::free(buf);
+ }
+ } else {
+ mpq_set_str(MP(new_quantity.get()), quant.c_str(), 10);
+ }
+
+ if (negative)
+ mpq_neg(MP(new_quantity.get()), MP(new_quantity.get()));
+
+ new_quantity->refc++;
+ quantity = new_quantity.release();
+
+ if (! flags.has_flags(PARSE_NO_REDUCE))
+ in_place_reduce(); // will not throw an exception
+
+ VERIFY(valid());
+
+ return true;
+}
+
+void amount_t::parse_conversion(const string& larger_str,
+ const string& smaller_str)
+{
+ amount_t larger, smaller;
+
+ larger.parse(larger_str, PARSE_NO_REDUCE);
+ smaller.parse(smaller_str, PARSE_NO_REDUCE);
+
+ larger *= smaller.number();
+
+ if (larger.commodity()) {
+ larger.commodity().set_smaller(smaller);
+ larger.commodity().add_flags(smaller.commodity().flags() |
+ COMMODITY_NOMARKET);
+ }
+ if (smaller.commodity())
+ smaller.commodity().set_larger(larger);
+}
+
+void amount_t::print(std::ostream& _out) const
+{
+ VERIFY(valid());
+
+ if (! quantity) {
+ _out << "<null>";
+ return;
+ }
+
+ std::ostringstream out;
+
+ commodity_t& comm(commodity());
+
+ if (! comm.has_flags(COMMODITY_STYLE_SUFFIXED)) {
+ comm.print(out);
+ if (comm.has_flags(COMMODITY_STYLE_SEPARATED))
+ out << " ";
+ }
+
+ stream_out_mpq(out, MP(quantity), display_precision(),
+ comm ? commodity().precision() : 0, comm);
+
+ if (comm.has_flags(COMMODITY_STYLE_SUFFIXED)) {
+ if (comm.has_flags(COMMODITY_STYLE_SEPARATED))
+ out << " ";
+ comm.print(out);
+ }
+
+ // If there are any annotations associated with this commodity, output them
+ // now.
+ comm.write_annotations(out);
+
+ // Things are output to a string first, so that if anyone has specified a
+ // width or fill for _out, it will be applied to the entire amount string,
+ // and not just the first part.
+ _out << out.str();
+}
+
+bool amount_t::valid() const
+{
+ if (quantity) {
+ if (! quantity->valid()) {
+ DEBUG("ledger.validate", "amount_t: ! quantity->valid()");
+ return false;
+ }
+
+ if (quantity->refc == 0) {
+ DEBUG("ledger.validate", "amount_t: quantity->refc == 0");
+ return false;
+ }
+ }
+ else if (commodity_) {
+ DEBUG("ledger.validate", "amount_t: commodity_ != NULL");
+ return false;
+ }
+ return true;
+}
+
+void to_xml(std::ostream& out, const amount_t& amt, bool commodity_details)
+{
+ push_xml x(out, "amount");
+
+ if (amt.has_commodity())
+ to_xml(out, amt.commodity(), commodity_details);
+
+ {
+ push_xml y(out, "quantity");
+ out << y.guard(amt.quantity_string());
+ }
+}
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+
+template<class Archive>
+void amount_t::serialize(Archive& ar, const unsigned int /* version */)
+{
+ ar & is_initialized;
+ ar & quantity;
+ ar & commodity_;
+}
+
+#endif // HAVE_BOOST_SERIALIZATION
+
+} // namespace ledger
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+namespace boost {
+namespace serialization {
+
+template <class Archive>
+void serialize(Archive& ar, MP_INT& mpz, const unsigned int /* version */)
+{
+ ar & mpz._mp_alloc;
+ ar & mpz._mp_size;
+ ar & mpz._mp_d;
+}
+
+template <class Archive>
+void serialize(Archive& ar, MP_RAT& mpq, const unsigned int /* version */)
+{
+ ar & mpq._mp_num;
+ ar & mpq._mp_den;
+}
+
+template <class Archive>
+void serialize(Archive& ar, long unsigned int& integer,
+ const unsigned int /* version */)
+{
+ ar & make_binary_object(&integer, sizeof(long unsigned int));
+}
+
+} // namespace serialization
+} // namespace boost
+
+BOOST_CLASS_EXPORT(ledger::annotated_commodity_t)
+
+template void boost::serialization::serialize(boost::archive::binary_iarchive&,
+ MP_INT&, const unsigned int);
+template void boost::serialization::serialize(boost::archive::binary_oarchive&,
+ MP_INT&, const unsigned int);
+template void boost::serialization::serialize(boost::archive::binary_iarchive&,
+ MP_RAT&, const unsigned int);
+template void boost::serialization::serialize(boost::archive::binary_oarchive&,
+ MP_RAT&, const unsigned int);
+template void boost::serialization::serialize(boost::archive::binary_iarchive&,
+ long unsigned int&,
+ const unsigned int);
+template void boost::serialization::serialize(boost::archive::binary_oarchive&,
+ long unsigned int&,
+ const unsigned int);
+
+template void ledger::amount_t::serialize(boost::archive::binary_iarchive&,
+ const unsigned int);
+template void ledger::amount_t::serialize(boost::archive::binary_oarchive&,
+ const unsigned int);
+
+#endif // HAVE_BOOST_SERIALIZATION
diff --git a/src/amount.h b/src/amount.h
new file mode 100644
index 00000000..a37efdb8
--- /dev/null
+++ b/src/amount.h
@@ -0,0 +1,761 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @defgroup math Mathematical objects
+ */
+
+/**
+ * @file amount.h
+ * @author John Wiegley
+ *
+ * @ingroup math
+ *
+ * @brief Basic type for handling commoditized math: amount_t
+ *
+ * An amount is the most basic numerical type in Ledger, and relies on
+ * commodity.h to represent commoditized amounts, which allows Ledger to
+ * handle mathematical expressions involving disparate commodities.
+ *
+ * Amounts can be of virtually infinite size and precision. When
+ * division or multiplication is performed, the precision is
+ * automatically expanded to include as many extra digits as necessary
+ * to avoid losing information.
+ */
+#ifndef _AMOUNT_H
+#define _AMOUNT_H
+
+#include "utils.h"
+#include "times.h"
+#include "flags.h"
+
+namespace ledger {
+
+class commodity_t;
+class annotation_t;
+class keep_details_t;
+class commodity_pool_t;
+
+DECLARE_EXCEPTION(amount_error, std::runtime_error);
+
+enum parse_flags_enum_t {
+ PARSE_DEFAULT = 0x00,
+ PARSE_PARTIAL = 0x01,
+ PARSE_SINGLE = 0x02,
+ PARSE_NO_MIGRATE = 0x04,
+ PARSE_NO_REDUCE = 0x08,
+ PARSE_NO_ASSIGN = 0x10,
+ PARSE_NO_DATES = 0x20,
+ PARSE_OP_CONTEXT = 0x40,
+ PARSE_SOFT_FAIL = 0x80
+};
+
+typedef basic_flags_t<parse_flags_enum_t, uint_least8_t> parse_flags_t;
+
+/**
+ * @brief Encapsulate infinite-precision commoditized amounts
+ *
+ * Used to represent commoditized infinite-precision numbers, and
+ * uncommoditized, plain numbers. In the commoditized case, commodities
+ * keep track of how they are used, and are always displayed back to the
+ * user after the same fashion. For uncommoditized numbers, no display
+ * truncation is ever done. In both cases, internal precision is always
+ * kept to an excessive degree.
+ */
+class amount_t
+ : public ordered_field_operators<amount_t,
+ ordered_field_operators<amount_t, double,
+ ordered_field_operators<amount_t, unsigned long,
+ ordered_field_operators<amount_t, long> > > >
+{
+public:
+ /** Ready the amount subsystem for use.
+ @note Normally called by session_t::initialize(). */
+ static void initialize();
+ /** Shutdown the amount subsystem and free all resources.
+ @note Normally called by session_t::shutdown(). */
+ static void shutdown();
+
+ static bool is_initialized;
+
+ /** The amount's decimal precision. */
+ typedef uint_least16_t precision_t;
+
+ /** Number of places of precision by which values are extended to
+ avoid losing precision during division and multiplication. */
+ static const std::size_t extend_by_digits = 6U;
+
+ /** If amounts should be streamed using to_fullstring() rather than
+ to_string(), so that complete precision is always displayed no matter
+ what the precision of an individual commodity may be. */
+ static bool stream_fullstrings;
+
+protected:
+ void _copy(const amount_t& amt);
+ void _dup();
+ void _clear();
+ void _release();
+
+ struct bigint_t;
+
+ bigint_t * quantity;
+ commodity_t * commodity_;
+
+public:
+ /** @name Constructors
+ @{ */
+
+ /** Creates a value for which is_null() is true, and which has no
+ value or commodity. If used in a value expression it evaluates to
+ zero, and its commodity equals \c commodity_t::null_commodity. */
+ amount_t() : quantity(NULL), commodity_(NULL) {
+ TRACE_CTOR(amount_t, "");
+ }
+
+ /** Convert a double to an amount. As much precision as possible is
+ decoded from the binary floating point number. */
+ amount_t(const double val);
+
+ /** Convert an unsigned long to an amount. It's precision is zero. */
+ amount_t(const unsigned long val);
+
+ /** Convert a long to an amount. It's precision is zero, and the sign
+ is preserved. */
+ amount_t(const long val);
+
+ /** Parse a string as an (optionally commoditized) amount. If no
+ commodity is present, the resulting commodity is \c
+ commodity_t::null_commodity. The number may be of infinite
+ precision. */
+ explicit amount_t(const string& val) : quantity(NULL) {
+ TRACE_CTOR(amount_t, "const string&");
+ parse(val);
+ }
+ /** Parse a pointer to a C string as an (optionally commoditized)
+ amount. If no commodity is present, the resulting commodity is \c
+ commodity_t::null_commodity. The number may be of infinite
+ precision. */
+ explicit amount_t(const char * val) : quantity(NULL) {
+ TRACE_CTOR(amount_t, "const char *");
+ assert(val);
+ parse(val);
+ }
+
+ /*@}*/
+
+ /** Create an amount whose display precision is never truncated, even
+ if the amount uses a commodity (which normally causes "round on
+ streaming" to occur). This function is mostly used by debugging
+ code and unit tests. This is the proper way to specify \c
+ $100.005, where display of the extra digit precision is required.
+ If a regular constructor were used, the amount would stream as \c
+ $100.01, even though its internal value equals \c $100.005. */
+ static amount_t exact(const string& value);
+
+ /** Release the reference count held for the underlying \c
+ amount_t::bigint_t object. */
+ ~amount_t() {
+ TRACE_DTOR(amount_t);
+ if (quantity)
+ _release();
+ }
+
+ /** @name Assignment and copy
+ @{*/
+
+ /** Copy an amount object. Copies are very efficient, using a
+ copy-on-write model. Until the copy is changed, it refers to the
+ same memory used by the original via reference counting. The \c
+ amount_t::bigint_t class in amount.cc maintains the reference. */
+ amount_t(const amount_t& amt) : quantity(NULL) {
+ TRACE_CTOR(amount_t, "copy");
+ if (amt.quantity)
+ _copy(amt);
+ else
+ commodity_ = NULL;
+ }
+ /** Copy an amount object, applying the given commodity annotation
+ details afterward. This is equivalent to doing a normal copy
+ (@see amount_t(const amount_t&)) and then calling
+ amount_t::annotate(). */
+ amount_t(const amount_t& amt, const annotation_t& details) : quantity(NULL) {
+ TRACE_CTOR(amount_t, "const amount_t&, const annotation_t&");
+ assert(amt.quantity);
+ _copy(amt);
+ annotate(details);
+ }
+ /** Assign an amount object. This is like copying if the amount was
+ null beforehand, otherwise the previous value's reference is must
+ be freed. */
+ amount_t& operator=(const amount_t& amt);
+
+ amount_t& operator=(const double val) {
+ return *this = amount_t(val);
+ }
+ amount_t& operator=(const unsigned long val) {
+ return *this = amount_t(val);
+ }
+ amount_t& operator=(const long val) {
+ return *this = amount_t(val);
+ }
+
+ /* Assign a string to an amount. This causes the contents of the
+ string to be parsed, look for a commoditized or uncommoditized
+ amount specifier. */
+ amount_t& operator=(const string& str) {
+ return *this = amount_t(str);
+ }
+ amount_t& operator=(const char * str) {
+ assert(str);
+ return *this = amount_t(str);
+ }
+
+ /*@}*/
+
+ /** @name Comparison
+ @{ */
+
+ /** Compare two amounts, returning a number less than zero if \p amt
+ is greater, exactly zero if they are equal, and greater than zero
+ if \p amt is less. This method is used to implement all of the
+ other comparison methods.*/
+ int compare(const amount_t& amt) const;
+
+ /** Test two amounts for equality. First the commodity pointers are
+ quickly tested, then the multi-precision values themselves must be
+ compared. */
+ bool operator==(const amount_t& amt) const;
+
+ template <typename T>
+ bool operator==(const T& val) const {
+ return compare(val) == 0;
+ }
+ template <typename T>
+ bool operator<(const T& amt) const {
+ return compare(amt) < 0;
+ }
+ template <typename T>
+ bool operator>(const T& amt) const {
+ return compare(amt) > 0;
+ }
+
+ /*@}*/
+
+ /** @name Binary arithmetic
+ */
+ /*@{*/
+
+ amount_t& operator+=(const amount_t& amt);
+ amount_t& operator-=(const amount_t& amt);
+ amount_t& operator*=(const amount_t& amt);
+
+ /** Divide two amounts while extending the precision to preserve the
+ accuracy of the result. For example, if \c 10 is divided by \c 3,
+ the result ends up having a precision of \link
+ amount_t::extend_by_digits \endlink place to avoid losing internal
+ resolution. */
+ amount_t& operator/=(const amount_t& amt);
+
+ /*@}*/
+
+ /** @name Unary arithmetic
+ @{ */
+
+ /** Return an amount's internal precision. To find the precision it
+ should be displayed at -- assuming it was not created using
+ amount_t::exact() -- use the following expression instead:
+ @code
+ amount.commodity().precision()
+ @endcode */
+ precision_t precision() const;
+ bool keep_precision() const;
+ void set_keep_precision(const bool keep = true) const;
+ precision_t display_precision() const;
+
+ /** Returns the negated value of an amount.
+ @see operator-()
+ */
+ amount_t negated() const {
+ amount_t temp(*this);
+ temp.in_place_negate();
+ return temp;
+ }
+ void in_place_negate();
+
+ amount_t operator-() const {
+ return negated();
+ }
+
+ /** Returns the absolute value of an amount. Equivalent to:
+ @code
+ (x < * 0) ? - x : x
+ @endcode
+ */
+ amount_t abs() const {
+ if (sign() < 0)
+ return negated();
+ return *this;
+ }
+
+ amount_t inverted() const;
+
+ /** Yields an amount whose display precision when output is truncated
+ to the display precision of its commodity. This is normally the
+ default state of an amount, but if one has become unrounded, this
+ sets the "keep precision" state back to false.
+ @see set_keep_precision */
+ amount_t rounded() const {
+ amount_t temp(*this);
+ temp.in_place_round();
+ return temp;
+ }
+ void in_place_round();
+
+ /** Yields an amount which has lost all of its extra precision, beyond what
+ the display precision of the commodity would have printed. */
+ amount_t truncated() const {
+ amount_t temp(*this);
+ temp.in_place_truncate();
+ return temp;
+ }
+ void in_place_truncate() {
+ *this = amount_t(to_string());
+ }
+
+ /** Yields an amount which has lost all of its extra precision, beyond what
+ the display precision of the commodity would have printed. */
+ amount_t floored() const {
+ amount_t temp(*this);
+ temp.in_place_floor();
+ return temp;
+ }
+ void in_place_floor();
+
+ /** Yields an amount whose display precision is never truncated, even
+ though its commodity normally displays only rounded values. */
+ amount_t unrounded() const {
+ amount_t temp(*this);
+ temp.in_place_unround();
+ return temp;
+ }
+ void in_place_unround();
+
+ /** reduces a value to its most basic commodity form, for amounts that
+ utilize "scaling commodities". For example, an amount of \c 1h
+ after reduction will be \c 3600s.
+ */
+ amount_t reduced() const {
+ amount_t temp(*this);
+ temp.in_place_reduce();
+ return temp;
+ }
+ void in_place_reduce();
+
+ /** unreduce(), if used with a "scaling commodity", yields the most
+ compact form greater than one. That is, \c 3599s will unreduce to
+ \c 59.98m, while \c 3601 unreduces to \c 1h.
+ */
+ amount_t unreduced() const {
+ amount_t temp(*this);
+ temp.in_place_unreduce();
+ return temp;
+ }
+ void in_place_unreduce();
+
+ /** Returns the historical value for an amount -- the default moment
+ returns the most recently known price -- based on the price history
+ for the given commodity (or determined automatically, if none is
+ provided). For example, if the amount were <tt>10 AAPL</tt>, and
+ on Apr 10, 2000 each share of \c AAPL was worth \c $10, then
+ calling value() for that moment in time would yield the amount \c
+ $100.00.
+ */
+ optional<amount_t>
+ value(const bool primary_only = true,
+ const optional<datetime_t>& moment = none,
+ const optional<commodity_t&>& in_terms_of = none) const;
+
+ amount_t price() const;
+
+ /*@}*/
+
+ /** @name Truth tests
+ */
+ /*@{*/
+
+ /** Truth tests. An amount may be truth test in several ways:
+
+ sign() returns an integer less than, greater than, or equal to
+ zero depending on whether the amount is negative, zero, or
+ greater than zero. Note that this function tests the actual
+ value of the amount -- using its internal precision -- and not
+ the display value. To test its display value, use:
+ `round().sign()'.
+
+ is_nonzero(), or operator bool, returns true if an amount's
+ display value is not zero.
+
+ is_zero() returns true if an amount's display value is zero.
+ Thus, $0.0001 is considered zero if the current display precision
+ for dollars is two decimal places.
+
+ is_realzero() returns true if an amount's actual value is zero.
+ Thus, $0.0001 is never considered realzero.
+
+ is_null() returns true if an amount has no value and no
+ commodity. This only occurs if an uninitialized amount has never
+ been assigned a value.
+ */
+ int sign() const;
+
+ operator bool() const {
+ return is_nonzero();
+ }
+ bool is_nonzero() const {
+ return ! is_zero();
+ }
+
+ bool is_zero() const;
+ bool is_realzero() const {
+ return sign() == 0;
+ }
+
+ bool is_null() const {
+ if (! quantity) {
+ assert(! commodity_);
+ return true;
+ }
+ return false;
+ }
+
+ /*@}*/
+
+ /** @name Conversion
+ */
+ /*@{*/
+
+ /** Conversion methods. An amount may be converted to the same types
+ it can be constructed from -- with the exception of unsigned
+ long. Implicit conversions are not allowed in C++ (though they
+ are in Python), rather the following conversion methods must be
+ called explicitly:
+
+ to_double([bool]) returns an amount as a double. If the optional
+ boolean argument is true (the default), an exception is thrown if
+ the conversion would lose information.
+
+ to_long([bool]) returns an amount as a long integer. If the
+ optional boolean argument is true (the default), an exception is
+ thrown if the conversion would lose information.
+
+ fits_in_long() returns true if to_long() would not lose
+ precision.
+
+ to_string() returns an amount'ss "display value" as a string --
+ after rounding the value according to the commodity's default
+ precision. It is equivalent to: `round().to_fullstring()'.
+
+ to_fullstring() returns an amount's "internal value" as a string,
+ without any rounding.
+
+ quantity_string() returns an amount's "display value", but
+ without any commodity. Note that this is different from
+ `number().to_string()', because in that case the commodity has
+ been stripped and the full, internal precision of the amount
+ would be displayed.
+ */
+ double to_double() const;
+ long to_long() const;
+ bool fits_in_long() const;
+
+ operator string() const {
+ return to_string();
+ }
+ string to_string() const;
+ string to_fullstring() const;
+ string quantity_string() const;
+
+ /*@}*/
+
+ /** @name Commodity methods
+ */
+ /*@{*/
+
+ /** The following methods relate to an
+ amount's commodity:
+
+ commodity() returns an amount's commodity. If the amount has no
+ commodity, the value returned is `current_pool->null_commodity'.
+
+ has_commodity() returns true if the amount has a commodity.
+
+ set_commodity(commodity_t) sets an amount's commodity to the
+ given value. Note that this merely sets the current amount to
+ that commodity, it does not "observe" the amount for possible
+ changes in the maximum display precision of the commodity, the
+ way that `parse' does.
+
+ clear_commodity() sets an amount's commodity to null, such that
+ has_commodity() afterwards returns false.
+
+ number() returns a commodity-less version of an amount. This is
+ useful for accessing just the numeric portion of an amount.
+ */
+ commodity_t& commodity() const;
+
+ bool has_commodity() const;
+ void set_commodity(commodity_t& comm) {
+ if (! quantity)
+ *this = 0L;
+ commodity_ = &comm;
+ }
+ void clear_commodity() {
+ commodity_ = NULL;
+ }
+
+ amount_t number() const {
+ if (! has_commodity())
+ return *this;
+
+ amount_t temp(*this);
+ temp.clear_commodity();
+ return temp;
+ }
+
+ /*@}*/
+
+ /** @name Commodity annotations
+ */
+ /*@{*/
+
+ /** An amount's commodity may be annotated with special details, such as the
+ price it was purchased for, when it was acquired, or an arbitrary note,
+ identifying perhaps the lot number of an item.
+
+ annotate_commodity(amount_t price, [datetime_t date, string tag])
+ sets the annotations for the current amount's commodity. Only
+ the price argument is required, although it can be passed as
+ `none' if no price is desired.
+
+ commodity_annotated() returns true if an amount's commodity has
+ any annotation details associated with it.
+
+ annotation_details() returns all of the details of an annotated
+ commodity's annotations. The structure returns will evaluate as
+ boolean false if there are no details.
+
+ strip_annotations() returns an amount whose commodity's annotations have
+ been stripped.
+ */
+ void annotate(const annotation_t& details);
+ bool has_annotation() const;
+
+ annotation_t& annotation();
+ const annotation_t& annotation() const {
+ return const_cast<amount_t&>(*this).annotation();
+ }
+
+ /** If the lot price is considered whenever working with commoditized
+ values.
+
+ Let's say a user adds two values of the following form:
+ @code
+ 10 AAPL + 10 AAPL {$20}
+ @endcode
+
+ This expression adds ten shares of Apple stock with another ten
+ shares that were purchased for \c $20 a share. If \c keep_price
+ is false, the result of this expression is an amount equal to
+ <tt>20 AAPL</tt>. If \c keep_price is \c true the expression
+ yields an exception for adding amounts with different commodities.
+ In that case, a \link balance_t \endlink object must be used to
+ store the combined sum. */
+ amount_t strip_annotations(const keep_details_t& what_to_keep) const;
+
+ /*@}*/
+
+ /** @name Parsing
+ */
+ /*@{*/
+
+ /** The `flags' argument of both parsing may be one or more of the
+ following:
+
+ PARSE_NO_MIGRATE means to not pay attention to the way an
+ amount is used. Ordinarily, if an amount were $100.001, for
+ example, it would cause the default display precision for $ to be
+ "widened" to three decimal places. If PARSE_NO_MIGRATE is
+ used, the commodity's default display precision is not changed.
+
+ PARSE_NO_REDUCE means not to call in_place_reduce() on the
+ resulting amount after it is parsed.
+
+ These parsing methods observe the amounts they parse (unless
+ PARSE_NO_MIGRATE is true), and set the display details of
+ the corresponding commodity accordingly. This way, amounts do
+ not require commodities to be pre-defined in any way, but merely
+ displays them back to the user in the same fashion as it saw them
+ used.
+
+ There is also a static convenience method called
+ `parse_conversion' which can be used to define a relationship
+ between scaling commodity values. For example, Ledger uses it to
+ define the relationships among various time values:
+
+ @code
+ amount_t::parse_conversion("1.0m", "60s"); // a minute is 60 seconds
+ amount_t::parse_conversion("1.0h", "60m"); // an hour is 60 minutes
+ @endcode
+
+ The method parse() is used to parse an amount from an input stream
+ or a string. A global operator>>() is also defined which simply
+ calls parse on the input stream. The parse() method has two forms:
+
+ parse(istream, flags_t) parses an amount from the given input
+ stream.
+
+ parse(string, flags_t) parses an amount from the given string.
+
+ parse(string, flags_t) also parses an amount from a string.
+ */
+ bool parse(std::istream& in,
+ const parse_flags_t& flags = PARSE_DEFAULT);
+ bool parse(const string& str,
+ const parse_flags_t& flags = PARSE_DEFAULT) {
+ std::istringstream stream(str);
+ bool result = parse(stream, flags);
+ return result;
+ }
+
+ static void parse_conversion(const string& larger_str,
+ const string& smaller_str);
+
+ /*@}*/
+
+ /** @name Printing
+ */
+ /*@{*/
+
+ /** An amount may be output to a stream using the `print' method. There is
+ also a global operator<< defined which simply calls print for an amount
+ on the given stream. There is one form of the print method, which takes
+ one required argument and two arguments with default values:
+
+ print(ostream, bool omit_commodity = false, bool full_precision = false)
+ prints an amounts to the given output stream, using its commodity's
+ default display characteristics. If `omit_commodity' is true, the
+ commodity will not be displayed, only the amount (although the
+ commodity's display precision is still used). If `full_precision' is
+ true, the full internal precision of the amount is displayed, regardless
+ of its commodity's display precision.
+ */
+ void print(std::ostream& out) const;
+
+ /*@}*/
+
+ /** @name Debugging
+ */
+ /*@{*/
+
+ /** There are two methods defined to help with debugging:
+
+ dump(ostream) dumps an amount to an output stream. There is
+ little different from print(), it simply surrounds the display
+ value with a marker, for example "AMOUNT($1.00)". This code is
+ used by other dumping code elsewhere in Ledger.
+
+ valid() returns true if an amount is valid. This ensures that if
+ an amount has a commodity, it has a valid value pointer, for
+ example, even if that pointer simply points to a zero value.
+ */
+ void dump(std::ostream& out) const {
+ out << "AMOUNT(";
+ print(out);
+ out << ")";
+ }
+
+ bool valid() const;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */);
+#endif // HAVE_BOOST_SERIALIZATION
+
+ /*@}*/
+};
+
+inline amount_t amount_t::exact(const string& value) {
+ amount_t temp;
+ temp.parse(value, PARSE_NO_MIGRATE);
+ return temp;
+}
+
+inline string amount_t::to_string() const {
+ std::ostringstream bufstream;
+ print(bufstream);
+ return bufstream.str();
+}
+
+inline string amount_t::to_fullstring() const {
+ std::ostringstream bufstream;
+ unrounded().print(bufstream);
+ return bufstream.str();
+}
+
+inline string amount_t::quantity_string() const {
+ std::ostringstream bufstream;
+ number().print(bufstream);
+ return bufstream.str();
+}
+
+inline std::ostream& operator<<(std::ostream& out, const amount_t& amt) {
+ if (amount_t::stream_fullstrings)
+ amt.unrounded().print(out);
+ else
+ amt.print(out);
+ return out;
+}
+inline std::istream& operator>>(std::istream& in, amount_t& amt) {
+ amt.parse(in);
+ return in;
+}
+
+void to_xml(std::ostream& out, const amount_t& amt,
+ bool commodity_details = false);
+
+} // namespace ledger
+
+#endif // _AMOUNT_H
diff --git a/src/annotate.cc b/src/annotate.cc
new file mode 100644
index 00000000..146a7afd
--- /dev/null
+++ b/src/annotate.cc
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "amount.h"
+#include "commodity.h"
+#include "annotate.h"
+#include "pool.h"
+
+namespace ledger {
+
+void annotation_t::parse(std::istream& in)
+{
+ do {
+ istream_pos_type pos = in.tellg();
+
+ char buf[256];
+ char c = peek_next_nonws(in);
+ if (c == '{') {
+ if (price)
+ throw_(amount_error, _("Commodity specifies more than one price"));
+
+ in.get(c);
+ c = peek_next_nonws(in);
+ if (c == '=') {
+ in.get(c);
+ add_flags(ANNOTATION_PRICE_FIXATED);
+ }
+
+ READ_INTO(in, buf, 255, c, c != '}');
+ if (c == '}')
+ in.get(c);
+ else
+ throw_(amount_error, _("Commodity price lacks closing brace"));
+
+ amount_t temp;
+ temp.parse(buf, PARSE_NO_MIGRATE);
+
+ DEBUG("commodity.annotations", "Parsed annotation price: " << temp);
+
+ // Since this price will maintain its own precision, make sure
+ // it is at least as large as the base commodity, since the user
+ // may have only specified {$1} or something similar.
+
+ if (temp.has_commodity() &&
+ temp.precision() > temp.commodity().precision())
+ temp = temp.rounded(); // no need to retain individual precision
+
+ price = temp;
+ }
+ else if (c == '[') {
+ if (date)
+ throw_(amount_error, _("Commodity specifies more than one date"));
+
+ in.get(c);
+ READ_INTO(in, buf, 255, c, c != ']');
+ if (c == ']')
+ in.get(c);
+ else
+ throw_(amount_error, _("Commodity date lacks closing bracket"));
+
+ date = parse_date(buf);
+ }
+ else if (c == '(') {
+ if (tag)
+ throw_(amount_error, _("Commodity specifies more than one tag"));
+
+ in.get(c);
+ READ_INTO(in, buf, 255, c, c != ')');
+ if (c == ')')
+ in.get(c);
+ else
+ throw_(amount_error, _("Commodity tag lacks closing parenthesis"));
+
+ tag = buf;
+ }
+ else {
+ in.clear();
+ in.seekg(pos, std::ios::beg);
+ break;
+ }
+ } while (true);
+
+#if defined(DEBUG_ON)
+ if (SHOW_DEBUG("amounts.commodities") && *this) {
+ DEBUG("amounts.commodities",
+ "Parsed commodity annotations: " << std::endl << *this);
+ }
+#endif
+}
+
+void annotation_t::print(std::ostream& out, bool keep_base) const
+{
+ if (price)
+ out << " {"
+ << (has_flags(ANNOTATION_PRICE_FIXATED) ? "=" : "")
+ << (keep_base ? *price : price->unreduced()).rounded()
+ << '}';
+
+ if (date)
+ out << " [" << format_date(*date, FMT_WRITTEN) << ']';
+
+ if (tag)
+ out << " (" << *tag << ')';
+}
+
+bool keep_details_t::keep_all(const commodity_t& comm) const
+{
+ return (! comm.has_annotation() ||
+ (keep_price && keep_date && keep_tag && ! only_actuals));
+}
+
+bool keep_details_t::keep_any(const commodity_t& comm) const
+{
+ return comm.has_annotation() && (keep_price || keep_date || keep_tag);
+}
+
+bool annotated_commodity_t::operator==(const commodity_t& comm) const
+{
+ // If the base commodities don't match, the game's up.
+ if (base != comm.base)
+ return false;
+
+ assert(annotated);
+ if (! comm.annotated)
+ return false;
+
+ if (details != as_annotated_commodity(comm).details)
+ return false;
+
+ return true;
+}
+
+commodity_t&
+annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep)
+{
+ DEBUG("commodity.annotated.strip",
+ "Reducing commodity " << *this << std::endl
+ << " keep price " << what_to_keep.keep_price << " "
+ << " keep date " << what_to_keep.keep_date << " "
+ << " keep tag " << what_to_keep.keep_tag);
+
+ commodity_t * new_comm;
+
+ bool keep_price = (what_to_keep.keep_price &&
+ (! what_to_keep.only_actuals ||
+ ! details.has_flags(ANNOTATION_PRICE_CALCULATED)));
+ bool keep_date = (what_to_keep.keep_date &&
+ (! what_to_keep.only_actuals ||
+ ! details.has_flags(ANNOTATION_DATE_CALCULATED)));
+ bool keep_tag = (what_to_keep.keep_tag &&
+ (! what_to_keep.only_actuals ||
+ ! details.has_flags(ANNOTATION_TAG_CALCULATED)));
+
+ if ((keep_price && details.price) ||
+ (keep_date && details.date) ||
+ (keep_tag && details.tag))
+ {
+ new_comm = pool().find_or_create
+ (referent(), annotation_t(keep_price ? details.price : none,
+ keep_date ? details.date : none,
+ keep_tag ? details.tag : none));
+ } else {
+ new_comm = pool().find_or_create(base_symbol());
+ }
+
+ assert(new_comm);
+ return *new_comm;
+}
+
+void annotated_commodity_t::write_annotations(std::ostream& out) const
+{
+ details.print(out, pool().keep_base);
+}
+
+} // namespace ledger
diff --git a/src/annotate.h b/src/annotate.h
new file mode 100644
index 00000000..38ebaeae
--- /dev/null
+++ b/src/annotate.h
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup math
+ */
+
+/**
+ * @file annotate.h
+ * @author John Wiegley
+ *
+ * @ingroup math
+ *
+ * @brief Types for annotating commodities
+ *
+ * Long.
+ */
+#ifndef _ANNOTATE_H
+#define _ANNOTATE_H
+
+namespace ledger {
+
+struct annotation_t : public supports_flags<>,
+ public equality_comparable<annotation_t>
+{
+#define ANNOTATION_PRICE_CALCULATED 0x01
+#define ANNOTATION_PRICE_FIXATED 0x02
+#define ANNOTATION_DATE_CALCULATED 0x04
+#define ANNOTATION_TAG_CALCULATED 0x08
+
+ optional<amount_t> price;
+ optional<date_t> date;
+ optional<string> tag;
+
+ explicit annotation_t(const optional<amount_t>& _price = none,
+ const optional<date_t>& _date = none,
+ const optional<string>& _tag = none)
+ : supports_flags<>(), price(_price), date(_date), tag(_tag) {
+ TRACE_CTOR(annotation_t, "const optional<amount_t>& + date_t + string");
+ }
+ annotation_t(const annotation_t& other)
+ : supports_flags<>(other.flags()),
+ price(other.price), date(other.date), tag(other.tag) {
+ TRACE_CTOR(annotation_t, "copy");
+ }
+ ~annotation_t() {
+ TRACE_DTOR(annotation_t);
+ }
+
+ operator bool() const {
+ return price || date || tag;
+ }
+
+ bool operator==(const annotation_t& rhs) const {
+ return (price == rhs.price &&
+ date == rhs.date &&
+ tag == rhs.tag);
+ }
+
+ void parse(std::istream& in);
+
+ void print(std::ostream& out, bool keep_base = false) const;
+
+ bool valid() const {
+ assert(*this);
+ return true;
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<supports_flags<> >(*this);
+ ar & price;
+ ar & date;
+ ar & tag;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+inline void to_xml(std::ostream& out, const annotation_t& details)
+{
+ push_xml x(out, "annotation");
+
+ if (details.price)
+ {
+ push_xml y(out, "price");
+ to_xml(out, *details.price);
+ }
+
+ if (details.date)
+ {
+ push_xml y(out, "date");
+ to_xml(out, *details.date, false);
+ }
+
+ if (details.tag)
+ {
+ push_xml y(out, "tag");
+ out << y.guard(*details.tag);
+ }
+}
+
+struct keep_details_t
+{
+ bool keep_price;
+ bool keep_date;
+ bool keep_tag;
+ bool only_actuals;
+
+ explicit keep_details_t(bool _keep_price = false,
+ bool _keep_date = false,
+ bool _keep_tag = false,
+ bool _only_actuals = false)
+ : keep_price(_keep_price),
+ keep_date(_keep_date),
+ keep_tag(_keep_tag),
+ only_actuals(_only_actuals)
+ {
+ TRACE_CTOR(keep_details_t, "bool, bool, bool, bool");
+ }
+ keep_details_t(const keep_details_t& other)
+ : keep_price(other.keep_price), keep_date(other.keep_date),
+ keep_tag(other.keep_tag), only_actuals(other.only_actuals) {
+ TRACE_CTOR(keep_details_t, "copy");
+ }
+ ~keep_details_t() throw() {
+ TRACE_DTOR(keep_details_t);
+ }
+
+ bool keep_all() const {
+ return keep_price && keep_date && keep_tag && ! only_actuals;
+ }
+ bool keep_all(const commodity_t& comm) const;
+
+ bool keep_any() const {
+ return keep_price || keep_date || keep_tag;
+ }
+ bool keep_any(const commodity_t& comm) const;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & keep_price;
+ ar & keep_date;
+ ar & keep_tag;
+ ar & only_actuals;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+inline std::ostream& operator<<(std::ostream& out,
+ const annotation_t& details) {
+ details.print(out);
+ return out;
+}
+
+class annotated_commodity_t
+ : public commodity_t,
+ public equality_comparable<annotated_commodity_t,
+ equality_comparable2<annotated_commodity_t, commodity_t,
+ noncopyable> >
+{
+protected:
+ friend class commodity_pool_t;
+
+ commodity_t * ptr;
+
+ explicit annotated_commodity_t(commodity_t * _ptr,
+ const annotation_t& _details)
+ : commodity_t(_ptr->parent_, _ptr->base), ptr(_ptr), details(_details) {
+ TRACE_CTOR(annotated_commodity_t, "commodity_t *, annotation_t");
+ annotated = true;
+ }
+
+public:
+ annotation_t details;
+
+ virtual ~annotated_commodity_t() {
+ TRACE_DTOR(annotated_commodity_t);
+ }
+
+ virtual bool operator==(const commodity_t& comm) const;
+ virtual bool operator==(const annotated_commodity_t& comm) const {
+ return *this == static_cast<const commodity_t&>(comm);
+ }
+
+ virtual commodity_t& referent() {
+ return *ptr;
+ }
+ virtual const commodity_t& referent() const {
+ return *ptr;
+ }
+
+ virtual commodity_t& strip_annotations(const keep_details_t& what_to_keep);
+ virtual void write_annotations(std::ostream& out) const;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ explicit annotated_commodity_t() : ptr(NULL) {
+ TRACE_CTOR(annotated_commodity_t, "");
+ }
+
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<commodity_t>(*this);
+ ar & ptr;
+ ar & details;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+inline annotated_commodity_t&
+as_annotated_commodity(commodity_t& commodity) {
+ return downcast<annotated_commodity_t>(commodity);
+}
+inline const annotated_commodity_t&
+as_annotated_commodity(const commodity_t& commodity) {
+ return downcast<const annotated_commodity_t>(commodity);
+}
+
+} // namespace ledger
+
+#endif // _ANNOTATE_H
diff --git a/src/archive.cc b/src/archive.cc
new file mode 100644
index 00000000..7306f8d3
--- /dev/null
+++ b/src/archive.cc
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+
+#include "archive.h"
+#include "amount.h"
+#include "commodity.h"
+#include "pool.h"
+#include "scope.h"
+#include "account.h"
+#include "post.h"
+#include "xact.h"
+
+#define LEDGER_MAGIC 0x4c454447
+#define ARCHIVE_VERSION 0x03000006
+
+//BOOST_IS_ABSTRACT(ledger::scope_t)
+BOOST_CLASS_EXPORT(ledger::scope_t)
+BOOST_CLASS_EXPORT(ledger::child_scope_t)
+BOOST_CLASS_EXPORT(ledger::symbol_scope_t)
+BOOST_CLASS_EXPORT(ledger::call_scope_t)
+BOOST_CLASS_EXPORT(ledger::account_t)
+BOOST_CLASS_EXPORT(ledger::item_t)
+BOOST_CLASS_EXPORT(ledger::post_t)
+BOOST_CLASS_EXPORT(ledger::xact_base_t)
+BOOST_CLASS_EXPORT(ledger::xact_t)
+BOOST_CLASS_EXPORT(ledger::auto_xact_t)
+BOOST_CLASS_EXPORT(ledger::period_xact_t)
+
+template void ledger::journal_t::serialize(boost::archive::binary_oarchive&,
+ const unsigned int);
+template void ledger::journal_t::serialize(boost::archive::binary_iarchive&,
+ const unsigned int);
+namespace ledger {
+
+namespace {
+ bool read_header_bits(std::istream& in) {
+ uint32_t bytes;
+
+ assert(sizeof(uint32_t) == 4);
+ in.read(reinterpret_cast<char *>(&bytes), sizeof(uint32_t));
+ if (bytes != LEDGER_MAGIC) {
+ DEBUG("archive.journal", "Magic bytes not present");
+ return false;
+ }
+
+ in.read(reinterpret_cast<char *>(&bytes), sizeof(uint32_t));
+ if (bytes != ARCHIVE_VERSION) {
+ DEBUG("archive.journal", "Archive version mismatch");
+ return false;
+ }
+
+ return true;
+ }
+
+ void write_header_bits(std::ostream& out) {
+ uint32_t bytes;
+
+ assert(sizeof(uint32_t) == 4);
+ bytes = LEDGER_MAGIC;
+ out.write(reinterpret_cast<char *>(&bytes), sizeof(uint32_t));
+
+ bytes = ARCHIVE_VERSION;
+ out.write(reinterpret_cast<char *>(&bytes), sizeof(uint32_t));
+ }
+}
+
+bool archive_t::read_header()
+{
+ uintmax_t size = file_size(file);
+ if (size < 8)
+ return false;
+
+ // Open the stream, read the version number and the list of sources
+ ifstream stream(file, std::ios::binary);
+ if (! read_header_bits(stream))
+ return false;
+
+ boost::archive::binary_iarchive iarchive(stream);
+
+ DEBUG("archive.journal", "Reading header from archive");
+ iarchive >> *this;
+
+ DEBUG("archive.journal",
+ "Version number: " << std::hex << ARCHIVE_VERSION << std::dec);
+ DEBUG("archive.journal", "Number of sources: " << sources.size());
+
+#if defined(DEBUG_ON)
+ foreach (const journal_t::fileinfo_t& i, sources)
+ DEBUG("archive.journal", "Loaded source: " << *i.filename);
+#endif
+
+ return true;
+}
+
+bool archive_t::should_load(const std::list<path>& data_files)
+{
+ std::size_t found = 0;
+
+ DEBUG("archive.journal", "Should the archive be loaded?");
+
+ if (! exists(file)) {
+ DEBUG("archive.journal", "No, it does not exist");
+ return false;
+ }
+
+ if (! read_header()) {
+ DEBUG("archive.journal", "No, header failed to read");
+ return false;
+ }
+
+ if (data_files.empty()) {
+ DEBUG("archive.journal", "No, there were no data files!");
+ return false;
+ }
+
+ if (sources.empty()) {
+ DEBUG("archive.journal", "No, there were no sources!");
+ return false;
+ }
+
+ if (data_files.size() != sources.size()) {
+ DEBUG("archive.journal", "No, number of sources doesn't match: "
+ << data_files.size() << " != " << sources.size());
+ return false;
+ }
+
+ foreach (const path& p, data_files) {
+ DEBUG("archive.journal", "Scanning for data file: " << p);
+
+ if (! exists(p)) {
+ DEBUG("archive.journal", "No, an input source no longer exists: " << p);
+ return false;
+ }
+
+ foreach (const journal_t::fileinfo_t& i, sources) {
+ assert(! i.from_stream);
+ assert(i.filename);
+
+ DEBUG("archive.journal", "Comparing against source file: " << *i.filename);
+
+ if (*i.filename == p) {
+ if (! exists(*i.filename)) {
+ DEBUG("archive.journal",
+ "No, a referent source no longer exists: " << *i.filename);
+ return false;
+ }
+
+ if (i.modtime != posix_time::from_time_t(last_write_time(p))) {
+ DEBUG("archive.journal", "No, a source's modtime has changed: " << p);
+ return false;
+ }
+
+ if (i.size != file_size(p)) {
+ DEBUG("archive.journal", "No, a source's size has changed: " << p);
+ return false;
+ }
+
+ found++;
+ }
+ }
+ }
+
+ if (found != data_files.size()) {
+ DEBUG("archive.journal", "No, not every source's name matched");
+ return false;
+ }
+
+ DEBUG("archive.journal", "Yes, it should be loaded!");
+ return true;
+}
+
+bool archive_t::should_save(journal_t& journal)
+{
+ std::list<path> data_files;
+
+ DEBUG("archive.journal", "Should the archive be saved?");
+
+ if (journal.was_loaded) {
+ DEBUG("archive.journal", "No, it's one we loaded before");
+ return false;
+ }
+
+ if (journal.sources.empty()) {
+ DEBUG("archive.journal", "No, there were no sources!");
+ return false;
+ }
+
+ foreach (const journal_t::fileinfo_t& i, journal.sources) {
+ if (i.from_stream) {
+ DEBUG("archive.journal", "No, one source was from a stream");
+ return false;
+ }
+
+ if (! exists(*i.filename)) {
+ DEBUG("archive.journal",
+ "No, a source no longer exists: " << *i.filename);
+ return false;
+ }
+
+ data_files.push_back(*i.filename);
+ }
+
+ if (should_load(data_files)) {
+ DEBUG("archive.journal", "No, because it's still loadable");
+ return false;
+ }
+
+ DEBUG("archive.journal", "Yes, it should be saved!");
+ return true;
+}
+
+void archive_t::save(journal_t& journal)
+{
+ INFO_START(archive, "Saved journal file cache");
+
+ ofstream stream(file, std::ios::binary);
+
+ write_header_bits(stream);
+ sources = journal.sources;
+
+#if defined(DEBUG_ON)
+ foreach (const journal_t::fileinfo_t& i, sources)
+ DEBUG("archive.journal", "Saving source: " << *i.filename);
+#endif
+
+ boost::archive::binary_oarchive oa(stream);
+
+ DEBUG("archive.journal", "Creating archive with version "
+ << std::hex << ARCHIVE_VERSION << std::dec);
+ oa << *this;
+
+ DEBUG("archive.journal",
+ "Archiving journal with " << sources.size() << " sources");
+ oa << journal;
+
+ INFO_FINISH(archive);
+}
+
+bool archive_t::load(journal_t& journal)
+{
+ INFO_START(archive, "Read cached journal file");
+
+ ifstream stream(file, std::ios::binary);
+ if (! read_header_bits(stream))
+ return false;
+
+ boost::archive::binary_iarchive iarchive(stream);
+
+ // Skip past the archive header, it was already read in before
+ archive_t temp;
+ iarchive >> temp;
+
+ iarchive >> journal;
+ journal.was_loaded = true;
+
+ INFO_FINISH(archive);
+
+ return true;
+}
+
+} // namespace ledger
+
+#endif // HAVE_BOOST_SERIALIZATION
diff --git a/src/archive.h b/src/archive.h
new file mode 100644
index 00000000..03fc970a
--- /dev/null
+++ b/src/archive.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @defgroup report Reporting
+ */
+
+/**
+ * @file archive.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _ARCHIVE_H
+#define _ARCHIVE_H
+
+#include "journal.h"
+
+namespace ledger {
+
+class archive_t
+{
+ path file;
+
+ std::list<journal_t::fileinfo_t> sources;
+
+public:
+ archive_t() {
+ TRACE_CTOR(archive_t, "");
+ }
+ archive_t(const path& _file) : file(_file) {
+ TRACE_CTOR(archive_t, "const path&");
+ }
+ archive_t(const archive_t& ar) : file(ar.file) {
+ TRACE_CTOR(archive_t, "copy");
+ }
+ ~archive_t() {
+ TRACE_DTOR(archive_t);
+ }
+
+ bool read_header();
+
+ bool should_load(const std::list<path>& data_files);
+ bool should_save(journal_t& journal);
+
+ void save(journal_t& journal);
+ bool load(journal_t& journal);
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & sources;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+} // namespace ledger
+
+#endif // _ARCHIVE_H
diff --git a/src/balance.cc b/src/balance.cc
new file mode 100644
index 00000000..4ff51ffc
--- /dev/null
+++ b/src/balance.cc
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "balance.h"
+#include "commodity.h"
+#include "annotate.h"
+#include "pool.h"
+#include "unistring.h" // for justify()
+
+namespace ledger {
+
+balance_t::balance_t(const double val)
+{
+ TRACE_CTOR(balance_t, "const double");
+ amounts.insert
+ (amounts_map::value_type(commodity_pool_t::current_pool->null_commodity, val));
+}
+
+balance_t::balance_t(const unsigned long val)
+{
+ TRACE_CTOR(balance_t, "const unsigned long");
+ amounts.insert
+ (amounts_map::value_type(commodity_pool_t::current_pool->null_commodity, val));
+}
+
+balance_t::balance_t(const long val)
+{
+ TRACE_CTOR(balance_t, "const long");
+ amounts.insert
+ (amounts_map::value_type(commodity_pool_t::current_pool->null_commodity, val));
+}
+
+balance_t& balance_t::operator+=(const balance_t& bal)
+{
+ foreach (const amounts_map::value_type& pair, bal.amounts)
+ *this += pair.second;
+ return *this;
+}
+
+balance_t& balance_t::operator+=(const amount_t& amt)
+{
+ if (amt.is_null())
+ throw_(balance_error,
+ _("Cannot add an uninitialized amount to a balance"));
+
+ if (amt.is_realzero())
+ return *this;
+
+ amounts_map::iterator i = amounts.find(&amt.commodity());
+ if (i != amounts.end())
+ i->second += amt;
+ else
+ amounts.insert(amounts_map::value_type(&amt.commodity(), amt));
+
+ return *this;
+}
+
+balance_t& balance_t::operator-=(const balance_t& bal)
+{
+ foreach (const amounts_map::value_type& pair, bal.amounts)
+ *this -= pair.second;
+ return *this;
+}
+
+balance_t& balance_t::operator-=(const amount_t& amt)
+{
+ if (amt.is_null())
+ throw_(balance_error,
+ _("Cannot subtract an uninitialized amount from a balance"));
+
+ if (amt.is_realzero())
+ return *this;
+
+ amounts_map::iterator i = amounts.find(&amt.commodity());
+ if (i != amounts.end()) {
+ i->second -= amt;
+ if (i->second.is_realzero())
+ amounts.erase(i);
+ } else {
+ amounts.insert(amounts_map::value_type(&amt.commodity(), amt.negated()));
+ }
+ return *this;
+}
+
+balance_t& balance_t::operator*=(const amount_t& amt)
+{
+ if (amt.is_null())
+ throw_(balance_error,
+ _("Cannot multiply a balance by an uninitialized amount"));
+
+ if (is_realzero()) {
+ ;
+ }
+ else if (amt.is_realzero()) {
+ *this = amt;
+ }
+ else if (! amt.commodity()) {
+ // Multiplying by an amount with no commodity causes all the
+ // component amounts to be increased by the same factor.
+ foreach (amounts_map::value_type& pair, amounts)
+ pair.second *= amt;
+ }
+ else if (amounts.size() == 1) {
+ // Multiplying by a commoditized amount is only valid if the sole
+ // commodity in the balance is of the same kind as the amount's
+ // commodity.
+ if (*amounts.begin()->first == amt.commodity())
+ amounts.begin()->second *= amt;
+ else
+ throw_(balance_error,
+ _("Cannot multiply a balance with annotated commodities by a commoditized amount"));
+ }
+ else {
+ assert(amounts.size() > 1);
+ throw_(balance_error,
+ _("Cannot multiply a multi-commodity balance by a commoditized amount"));
+ }
+ return *this;
+}
+
+balance_t& balance_t::operator/=(const amount_t& amt)
+{
+ if (amt.is_null())
+ throw_(balance_error,
+ _("Cannot divide a balance by an uninitialized amount"));
+
+ if (is_realzero()) {
+ ;
+ }
+ else if (amt.is_realzero()) {
+ throw_(balance_error, _("Divide by zero"));
+ }
+ else if (! amt.commodity()) {
+ // Dividing by an amount with no commodity causes all the
+ // component amounts to be divided by the same factor.
+ foreach (amounts_map::value_type& pair, amounts)
+ pair.second /= amt;
+ }
+ else if (amounts.size() == 1) {
+ // Dividing by a commoditized amount is only valid if the sole
+ // commodity in the balance is of the same kind as the amount's
+ // commodity.
+ if (*amounts.begin()->first == amt.commodity())
+ amounts.begin()->second /= amt;
+ else
+ throw_(balance_error,
+ _("Cannot divide a balance with annotated commodities by a commoditized amount"));
+ }
+ else {
+ assert(amounts.size() > 1);
+ throw_(balance_error,
+ _("Cannot divide a multi-commodity balance by a commoditized amount"));
+ }
+ return *this;
+}
+
+optional<balance_t>
+balance_t::value(const bool primary_only,
+ const optional<datetime_t>& moment,
+ const optional<commodity_t&>& in_terms_of) const
+{
+ balance_t temp;
+ bool resolved = false;
+
+ foreach (const amounts_map::value_type& pair, amounts) {
+ if (optional<amount_t> val = pair.second.value(primary_only, moment,
+ in_terms_of)) {
+ temp += *val;
+ resolved = true;
+ } else {
+ temp += pair.second;
+ }
+ }
+ return resolved ? temp : optional<balance_t>();
+}
+
+balance_t balance_t::price() const
+{
+ balance_t temp;
+
+ foreach (const amounts_map::value_type& pair, amounts)
+ temp += pair.second.price();
+
+ return temp;
+}
+
+optional<amount_t>
+balance_t::commodity_amount(const optional<const commodity_t&>& commodity) const
+{
+ if (! commodity) {
+ if (amounts.size() == 1) {
+ return amounts.begin()->second;
+ }
+ else if (amounts.size() > 1) {
+ // Try stripping annotations before giving an error.
+ balance_t temp(strip_annotations(keep_details_t()));
+ if (temp.amounts.size() == 1)
+ return temp.commodity_amount(commodity);
+
+ throw_(amount_error,
+ _("Requested amount of a balance with multiple commodities: %1")
+ << temp);
+ }
+ }
+ else if (amounts.size() > 0) {
+ amounts_map::const_iterator i =
+ amounts.find(const_cast<commodity_t *>(&*commodity));
+ if (i != amounts.end())
+ return i->second;
+ }
+ return none;
+}
+
+balance_t
+balance_t::strip_annotations(const keep_details_t& what_to_keep) const
+{
+ balance_t temp;
+
+ foreach (const amounts_map::value_type& pair, amounts)
+ temp += pair.second.strip_annotations(what_to_keep);
+
+ return temp;
+}
+
+void balance_t::print(std::ostream& out,
+ const int first_width,
+ const int latter_width,
+ const bool right_justify,
+ const bool colorize) const
+{
+ bool first = true;
+ int lwidth = latter_width;
+
+ if (lwidth == -1)
+ lwidth = first_width;
+
+ typedef std::vector<const amount_t *> amounts_array;
+ amounts_array sorted;
+
+ foreach (const amounts_map::value_type& pair, amounts)
+ if (pair.second)
+ sorted.push_back(&pair.second);
+
+ std::stable_sort(sorted.begin(), sorted.end(), compare_amount_commodities());
+
+ foreach (const amount_t * amount, sorted) {
+ int width;
+ if (! first) {
+ out << std::endl;
+ width = lwidth;
+ } else {
+ first = false;
+ width = first_width;
+ }
+
+ std::ostringstream buf;
+ buf << *amount;
+ justify(out, buf.str(), width, right_justify,
+ colorize && amount->sign() < 0);
+ }
+
+ if (first) {
+ out.width(first_width);
+ if (right_justify)
+ out << std::right;
+ else
+ out << std::left;
+ out << 0;
+ }
+}
+
+void to_xml(std::ostream& out, const balance_t& bal)
+{
+ push_xml x(out, "balance");
+
+ foreach (const balance_t::amounts_map::value_type& pair, bal.amounts)
+ to_xml(out, pair.second);
+}
+
+} // namespace ledger
diff --git a/src/balance.h b/src/balance.h
new file mode 100644
index 00000000..826de134
--- /dev/null
+++ b/src/balance.h
@@ -0,0 +1,602 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup math
+ */
+
+/**
+ * @file balance.h
+ * @author John Wiegley
+ *
+ * @ingroup math
+ *
+ * @brief Basic type for adding multiple commodities together
+ *
+ * Unlike the amount_t class, which throws an exception if amounts of
+ * differing commodities are added or subtracted, the balance_t class
+ * is designed to allow this, tracking the amounts of each component
+ * commodity separately.
+ */
+#ifndef _BALANCE_H
+#define _BALANCE_H
+
+#include "amount.h"
+
+namespace ledger {
+
+DECLARE_EXCEPTION(balance_error, std::runtime_error);
+
+/**
+ * @class balance_t
+ *
+ * @brief A wrapper around amount_t allowing addition of multiple commodities.
+ *
+ * The balance_t class is appopriate for keeping a running balance
+ * where amounts of multiple commodities may be involved.
+ */
+class balance_t
+ : public equality_comparable<balance_t,
+ equality_comparable<balance_t, amount_t,
+ equality_comparable<balance_t, double,
+ equality_comparable<balance_t, unsigned long,
+ equality_comparable<balance_t, long,
+ additive<balance_t,
+ additive<balance_t, amount_t,
+ additive<balance_t, double,
+ additive<balance_t, unsigned long,
+ additive<balance_t, long,
+ multiplicative<balance_t, amount_t,
+ multiplicative<balance_t, double,
+ multiplicative<balance_t, unsigned long,
+ multiplicative<balance_t, long> > > > > > > > > > > > > >
+{
+public:
+ typedef std::map<commodity_t *, amount_t> amounts_map;
+
+ amounts_map amounts;
+
+ /**
+ * Constructors. balance_t supports similar forms of construction
+ * to amount_t.
+ *
+ * balance_t() creates an empty balance to which amounts or other
+ * balances may be added or subtracted.
+ *
+ * balance_t(amount_t) constructs a balance whose starting value is
+ * equal to the given amount.
+ *
+ * balance_t(double), balance_t(unsigned long) and balance_t(long)
+ * will construct an amount from their arguments and then construct
+ * a balance whose starting value is equal to that amount. This
+ * initial balance will have no commodity.
+ *
+ * balance_t(string) and balance_t(const char *) both convert from a
+ * string representation of an amount to a balance whose initial
+ * value is that amount. This is the proper way to initialize a
+ * balance like '$100.00'.
+ */
+ balance_t() {
+ TRACE_CTOR(balance_t, "");
+ }
+ balance_t(const amount_t& amt) {
+ TRACE_CTOR(balance_t, "const amount_t&");
+ if (amt.is_null())
+ throw_(balance_error,
+ _("Cannot initialize a balance from an uninitialized amount"));
+ if (! amt.is_realzero())
+ amounts.insert(amounts_map::value_type(&amt.commodity(), amt));
+ }
+ balance_t(const double val);
+ balance_t(const unsigned long val);
+ balance_t(const long val);
+
+ explicit balance_t(const string& val) {
+ TRACE_CTOR(balance_t, "const string&");
+ amount_t temp(val);
+ amounts.insert(amounts_map::value_type(&temp.commodity(), temp));
+ }
+ explicit balance_t(const char * val) {
+ TRACE_CTOR(balance_t, "const char *");
+ amount_t temp(val);
+ amounts.insert(amounts_map::value_type(&temp.commodity(), temp));
+ }
+
+ /**
+ * Destructor. Destroys all of the accumulated amounts in the
+ * balance.
+ */
+ ~balance_t() {
+ TRACE_DTOR(balance_t);
+ }
+
+ /**
+ * Assignment and copy operators. An balance may be assigned or copied.
+ */
+ balance_t(const balance_t& bal) : amounts(bal.amounts) {
+ TRACE_CTOR(balance_t, "copy");
+ }
+
+ balance_t& operator=(const balance_t& bal) {
+ if (this != &bal)
+ amounts = bal.amounts;
+ return *this;
+ }
+ balance_t& operator=(const amount_t& amt) {
+ if (amt.is_null())
+ throw_(balance_error,
+ _("Cannot assign an uninitialized amount to a balance"));
+
+ amounts.clear();
+ if (! amt.is_realzero())
+ amounts.insert(amounts_map::value_type(&amt.commodity(), amt));
+
+ return *this;
+ }
+
+ balance_t& operator=(const string& str) {
+ return *this = balance_t(str);
+ }
+ balance_t& operator=(const char * str) {
+ return *this = balance_t(str);
+ }
+
+ /**
+ * Comparison operators. Balances are fairly restrictive in terms
+ * of how they may be compared. They may be compared for equality
+ * or inequality, but this is all, since the concept of "less than"
+ * or "greater than" makes no sense when amounts of multiple
+ * commodities are involved.
+ *
+ * Balances may also be compared to amounts, in which case the sum
+ * of the balance must equal the amount exactly.
+ *
+ * If a comparison between balances is desired, the balances must
+ * first be rendered to value equivalent amounts using the `value'
+ * method, to determine a market valuation at some specific moment
+ * in time.
+ */
+ bool operator==(const balance_t& bal) const {
+ amounts_map::const_iterator i, j;
+ for (i = amounts.begin(), j = bal.amounts.begin();
+ i != amounts.end() && j != bal.amounts.end();
+ i++, j++) {
+ if (! (i->first == j->first && i->second == j->second))
+ return false;
+ }
+ return i == amounts.end() && j == bal.amounts.end();
+ }
+ bool operator==(const amount_t& amt) const {
+ if (amt.is_null())
+ throw_(balance_error,
+ _("Cannot compare a balance to an uninitialized amount"));
+
+ if (amt.is_realzero())
+ return amounts.empty();
+ else
+ return amounts.size() == 1 && amounts.begin()->second == amt;
+ }
+
+ template <typename T>
+ bool operator==(const T& val) const {
+ return *this == amount_t(val);
+ }
+
+ /**
+ * Binary arithmetic operators. Balances support addition and
+ * subtraction of other balances or amounts, but multiplication and
+ * division are restricted to uncommoditized amounts only.
+ */
+ balance_t& operator+=(const balance_t& bal);
+ balance_t& operator+=(const amount_t& amt);
+ balance_t& operator+=(const double val) {
+ return *this += amount_t(val);
+ }
+ balance_t& operator+=(const unsigned long val) {
+ return *this += amount_t(val);
+ }
+ balance_t& operator+=(const long val) {
+ return *this += amount_t(val);
+ }
+
+ balance_t& operator-=(const balance_t& bal);
+ balance_t& operator-=(const amount_t& amt);
+ balance_t& operator-=(const double val) {
+ return *this -= amount_t(val);
+ }
+ balance_t& operator-=(const unsigned long val) {
+ return *this -= amount_t(val);
+ }
+ balance_t& operator-=(const long val) {
+ return *this -= amount_t(val);
+ }
+
+ balance_t& operator*=(const amount_t& amt);
+ balance_t& operator*=(const double val) {
+ return *this *= amount_t(val);
+ }
+ balance_t& operator*=(const unsigned long val) {
+ return *this *= amount_t(val);
+ }
+ balance_t& operator*=(const long val) {
+ return *this *= amount_t(val);
+ }
+
+ balance_t& operator/=(const amount_t& amt);
+ balance_t& operator/=(const double val) {
+ return *this /= amount_t(val);
+ }
+ balance_t& operator/=(const unsigned long val) {
+ return *this /= amount_t(val);
+ }
+ balance_t& operator/=(const long val) {
+ return *this /= amount_t(val);
+ }
+
+ /**
+ * Unary arithmetic operators. There are only a few unary methods
+ * support on balance:
+ *
+ * negate(), also unary minus (- x), returns a balance all of whose
+ * component amounts have been negated. In order words, it inverts
+ * the sign of all member amounts.
+ *
+ * abs() returns a balance where no component amount is negative.
+ *
+ * reduce() reduces the values in a balance to their most basic
+ * commodity forms, for amounts that utilize "scaling commodities".
+ * For example, a balance of 1h and 1m after reduction will be
+ * 3660s.
+ *
+ * unreduce(), if used with amounts that use "scaling commodities",
+ * yields the most compact form greater than 1.0 for each component
+ * amount. That is, a balance of 10m and 1799s will unreduce to
+ * 39.98m.
+ *
+ * value(optional<datetime_t>) returns the total historical value for
+ * a balance -- the default moment returns a value based on the most
+ * recently known price -- based on the price history of its
+ * component commodities. See amount_t::value for an example.
+ *
+ * Further, for the sake of efficiency and avoiding temporary
+ * objects, the following methods support "in-place" variants act on
+ * the balance itself and return a reference to the result
+ * (`*this'):
+ *
+ * in_place_negate()
+ * in_place_reduce()
+ * in_place_unreduce()
+ */
+ balance_t negated() const {
+ balance_t temp(*this);
+ temp.in_place_negate();
+ return temp;
+ }
+ void in_place_negate() {
+ foreach (amounts_map::value_type& pair, amounts)
+ pair.second.in_place_negate();
+ }
+ balance_t operator-() const {
+ return negated();
+ }
+
+ balance_t abs() const {
+ balance_t temp;
+ foreach (const amounts_map::value_type& pair, amounts)
+ temp += pair.second.abs();
+ return temp;
+ }
+
+ balance_t rounded() const {
+ balance_t temp(*this);
+ temp.in_place_round();
+ return temp;
+ }
+ void in_place_round() {
+ balance_t temp;
+ foreach (const amounts_map::value_type& pair, amounts)
+ temp += pair.second.rounded();
+ *this = temp;
+ }
+
+ balance_t truncated() const {
+ balance_t temp(*this);
+ temp.in_place_truncate();
+ return temp;
+ }
+ void in_place_truncate() {
+ balance_t temp;
+ foreach (const amounts_map::value_type& pair, amounts)
+ temp += pair.second.truncated();
+ *this = temp;
+ }
+
+ balance_t floored() const {
+ balance_t temp(*this);
+ temp.in_place_floor();
+ return temp;
+ }
+ void in_place_floor() {
+ balance_t temp;
+ foreach (const amounts_map::value_type& pair, amounts)
+ temp += pair.second.floored();
+ *this = temp;
+ }
+
+ balance_t unrounded() const {
+ balance_t temp(*this);
+ temp.in_place_unround();
+ return temp;
+ }
+ void in_place_unround() {
+ balance_t temp;
+ foreach (const amounts_map::value_type& pair, amounts)
+ temp += pair.second.unrounded();
+ *this = temp;
+ }
+
+ balance_t reduced() const {
+ balance_t temp(*this);
+ temp.in_place_reduce();
+ return temp;
+ }
+ void in_place_reduce() {
+ // A temporary must be used here because reduction may cause
+ // multiple component amounts to collapse to the same commodity.
+ balance_t temp;
+ foreach (const amounts_map::value_type& pair, amounts)
+ temp += pair.second.reduced();
+ *this = temp;
+ }
+
+ balance_t unreduced() const {
+ balance_t temp(*this);
+ temp.in_place_unreduce();
+ return temp;
+ }
+ void in_place_unreduce() {
+ // A temporary must be used here because unreduction may cause
+ // multiple component amounts to collapse to the same commodity.
+ balance_t temp;
+ foreach (const amounts_map::value_type& pair, amounts)
+ temp += pair.second.unreduced();
+ *this = temp;
+ }
+
+ optional<balance_t>
+ value(const bool primary_only = false,
+ const optional<datetime_t>& moment = none,
+ const optional<commodity_t&>& in_terms_of = none) const;
+
+ balance_t price() const;
+
+ /**
+ * Truth tests. An balance may be truth test in two ways:
+ *
+ * is_nonzero(), or operator bool, returns true if a balance's
+ * display value is not zero.
+ *
+ * is_zero() returns true if an balance's display value is zero.
+ * Thus, a balance containing $0.0001 is considered zero if the
+ * current display precision for dollars is two decimal places.
+ *
+ * is_realzero() returns true if an balance's actual value is zero.
+ * Thus, a balance containing $0.0001 is never considered realzero.
+ *
+ * is_empty() returns true if a balance has no amounts within it.
+ * This can occur after a balance has been default initialized, or
+ * if the exact amount it contains is subsequently subtracted from
+ * it.
+ */
+ operator bool() const {
+ return is_nonzero();
+ }
+
+ bool is_nonzero() const {
+ if (is_empty())
+ return false;
+
+ foreach (const amounts_map::value_type& pair, amounts)
+ if (pair.second.is_nonzero())
+ return true;
+ return false;
+ }
+
+ bool is_zero() const {
+ if (is_empty())
+ return true;
+
+ foreach (const amounts_map::value_type& pair, amounts)
+ if (! pair.second.is_zero())
+ return false;
+ return true;
+ }
+
+ bool is_realzero() const {
+ if (is_empty())
+ return true;
+
+ foreach (const amounts_map::value_type& pair, amounts)
+ if (! pair.second.is_realzero())
+ return false;
+ return true;
+ }
+
+ bool is_empty() const {
+ return amounts.size() == 0;
+ }
+ bool single_amount() const {
+ return amounts.size() == 1;
+ }
+
+ /**
+ * Conversion methods. A balance can be converted to an amount, but
+ * only if contains a single component amount.
+ */
+ operator string() const {
+ return to_string();
+ }
+ string to_string() const {
+ std::ostringstream buf;
+ print(buf);
+ return buf.str();
+ }
+
+ amount_t to_amount() const {
+ if (is_empty())
+ throw_(balance_error, _("Cannot convert an empty balance to an amount"));
+ else if (amounts.size() == 1)
+ return amounts.begin()->second;
+ else
+ throw_(balance_error,
+ _("Cannot convert a balance with multiple commodities to an amount"));
+ return amount_t();
+ }
+
+ /**
+ * Commodity-related methods. Balances support two
+ * commodity-related methods:
+ *
+ * commodity_count() returns the number of different commodities
+ * stored in the balance.
+ *
+ * commodity_amount(optional<commodity_t>) returns an (optional)
+ * amount for the given commodity within the balance; if no
+ * commodity is specified, it returns the (optional) uncommoditized
+ * component of the balance. If no matching element can be found,
+ * boost::none is returned.
+ */
+ std::size_t commodity_count() const {
+ return amounts.size();
+ }
+
+ optional<amount_t>
+ commodity_amount(const optional<const commodity_t&>& commodity = none) const;
+
+ balance_t number() const {
+ balance_t temp;
+ foreach (const amounts_map::value_type& pair, amounts)
+ temp += pair.second.number();
+ return temp;
+ }
+
+ /**
+ * Annotated commodity methods. The amounts contained by a balance
+ * may use annotated commodities. The `strip_annotations' method
+ * will return a balance all of whose component amount have had
+ * their commodity annotations likewise stripped. See
+ * amount_t::strip_annotations for more details.
+ */
+ balance_t strip_annotations(const keep_details_t& what_to_keep) const;
+
+ /**
+ * Printing methods. A balance may be output to a stream using the
+ * `print' method. There is also a global operator<< defined which
+ * simply calls print for a balance on the given stream. There is
+ * one form of the print method, which takes two required arguments
+ * and one arguments with a default value:
+ *
+ * print(ostream, int first_width, int latter_width) prints a
+ * balance to the given output stream, using each commodity's
+ * default display characteristics. The first_width parameter
+ * specifies the width that should be used for printing amounts
+ * (since they are likely to vary in width). The latter_width, if
+ * specified, gives the width to be used for each line after the
+ * first. This is useful when printing in a column which falls at
+ * the right-hand side of the screen.
+ *
+ * In addition to the width constraints, balances will also print
+ * with commodities in alphabetized order, regardless of the
+ * relative amounts of those commodities. There is no option to
+ * change this behavior.
+ */
+ void print(std::ostream& out,
+ const int first_width = -1,
+ const int latter_width = -1,
+ const bool right_justify = false,
+ const bool colorize = false) const;
+
+ /**
+ * Debugging methods. There are two methods defined to help with
+ * debugging:
+ *
+ * dump(ostream) dumps a balance to an output stream. There is
+ * little different from print(), it simply surrounds the display
+ * value with a marker, for example "BALANCE($1.00, DM 12.00)".
+ * This code is used by other dumping code elsewhere in Ledger.
+ *
+ * valid() returns true if the amounts within the balance are valid.
+ */
+ void dump(std::ostream& out) const {
+ out << "BALANCE(";
+ bool first = true;
+ foreach (const amounts_map::value_type& pair, amounts) {
+ if (first)
+ first = false;
+ else
+ out << ", ";
+ pair.second.print(out);
+ }
+ out << ")";
+ }
+
+ bool valid() const {
+ foreach (const amounts_map::value_type& pair, amounts)
+ if (! pair.second.valid()) {
+ DEBUG("ledger.validate", "balance_t: ! pair.second.valid()");
+ return false;
+ }
+ return true;
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & amounts;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) {
+ bal.print(out, 12);
+ return out;
+}
+
+void to_xml(std::ostream& out, const balance_t& amt);
+
+} // namespace ledger
+
+#endif // _BALANCE_H
diff --git a/src/chain.cc b/src/chain.cc
new file mode 100644
index 00000000..113a71d8
--- /dev/null
+++ b/src/chain.cc
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "chain.h"
+#include "predicate.h"
+#include "filters.h"
+#include "report.h"
+#include "session.h"
+
+namespace ledger {
+
+post_handler_ptr chain_post_handlers(report_t& report,
+ post_handler_ptr base_handler,
+ bool for_accounts_report)
+{
+ post_handler_ptr handler(base_handler);
+ predicate_t display_predicate;
+ predicate_t only_predicate;
+
+ assert(report.HANDLED(amount_));
+ expr_t& expr(report.HANDLER(amount_).expr);
+ expr.set_context(&report);
+
+ if (! for_accounts_report) {
+ // Make sure only forecast postings which match are allowed through
+ if (report.HANDLED(forecast_while_)) {
+ handler.reset(new filter_posts
+ (handler, predicate_t(report.HANDLER(forecast_while_).str(),
+ report.what_to_keep()),
+ report));
+ }
+
+ // truncate_xacts cuts off a certain number of _xacts_ from being
+ // displayed. It does not affect calculation.
+ if (report.HANDLED(head_) || report.HANDLED(tail_))
+ handler.reset
+ (new truncate_xacts(handler,
+ report.HANDLED(head_) ?
+ report.HANDLER(head_).value.to_int() : 0,
+ report.HANDLED(tail_) ?
+ report.HANDLER(tail_).value.to_int() : 0));
+
+ // filter_posts will only pass through posts matching the
+ // `display_predicate'.
+ if (report.HANDLED(display_)) {
+ display_predicate = predicate_t(report.HANDLER(display_).str(),
+ report.what_to_keep());
+ handler.reset(new filter_posts(handler, display_predicate, report));
+ }
+ }
+
+ // changed_value_posts adds virtual posts to the list to account for changes
+ // in market value of commodities, which otherwise would affect the running
+ // total unpredictably.
+ if (report.HANDLED(revalued) && (! for_accounts_report ||
+ report.HANDLED(unrealized)))
+ handler.reset(new changed_value_posts(handler, report,
+ for_accounts_report,
+ report.HANDLED(unrealized)));
+
+ // calc_posts computes the running total. When this appears will determine,
+ // for example, whether filtered posts are included or excluded from the
+ // running total.
+ handler.reset(new calc_posts(handler, expr, (! for_accounts_report ||
+ (report.HANDLED(revalued) &&
+ report.HANDLED(unrealized)))));
+
+ // filter_posts will only pass through posts matching the
+ // `secondary_predicate'.
+ if (report.HANDLED(only_)) {
+ only_predicate = predicate_t(report.HANDLER(only_).str(),
+ report.what_to_keep());
+ handler.reset(new filter_posts(handler, only_predicate, report));
+ }
+
+ if (! for_accounts_report) {
+ // sort_posts will sort all the posts it sees, based on the `sort_order'
+ // value expression.
+ if (report.HANDLED(sort_)) {
+ if (report.HANDLED(sort_xacts_))
+ handler.reset(new sort_xacts(handler, report.HANDLER(sort_).str()));
+ else
+ handler.reset(new sort_posts(handler, report.HANDLER(sort_).str()));
+ }
+ else if (! report.HANDLED(period_) &&
+ ! report.HANDLED(unsorted)) {
+ handler.reset(new sort_posts(handler, "date"));
+ }
+
+ // collapse_posts causes xacts with multiple posts to appear as xacts
+ // with a subtotaled post for each commodity used.
+ if (report.HANDLED(collapse))
+ handler.reset(new collapse_posts(handler, expr,
+ display_predicate, only_predicate,
+ report.HANDLED(collapse_if_zero)));
+
+ // subtotal_posts combines all the posts it receives into one subtotal
+ // xact, which has one post for each commodity in each account.
+ //
+ // period_posts is like subtotal_posts, but it subtotals according to time
+ // periods rather than totalling everything.
+ //
+ // dow_posts is like period_posts, except that it reports all the posts
+ // that fall on each subsequent day of the week.
+ if (report.HANDLED(equity))
+ handler.reset(new posts_as_equity(handler, expr));
+ else if (report.HANDLED(subtotal))
+ handler.reset(new subtotal_posts(handler, expr));
+ }
+
+ if (report.HANDLED(dow))
+ handler.reset(new dow_posts(handler, expr));
+ else if (report.HANDLED(by_payee))
+ handler.reset(new by_payee_posts(handler, expr));
+
+ // interval_posts groups posts together based on a time period, such as
+ // weekly or monthly.
+ if (report.HANDLED(period_)) {
+ handler.reset(new interval_posts(handler, expr,
+ report.HANDLER(period_).str(),
+ report.HANDLED(exact),
+ report.HANDLED(empty)));
+ handler.reset(new sort_posts(handler, "date"));
+ }
+
+ if (report.HANDLED(date_))
+ handler.reset(new transfer_details(handler, transfer_details::SET_DATE,
+ report.session.journal->master,
+ report.HANDLER(date_).str(),
+ report));
+ if (report.HANDLED(account_))
+ handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
+ report.session.journal->master,
+ report.HANDLER(account_).str(),
+ report));
+ if (report.HANDLED(payee_))
+ handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE,
+ report.session.journal->master,
+ report.HANDLER(payee_).str(),
+ report));
+
+ // related_posts will pass along all posts related to the post received. If
+ // the `related_all' handler is on, then all the xact's posts are passed;
+ // meaning that if one post of an xact is to be printed, all the post for
+ // that xact will be printed.
+ if (report.HANDLED(related))
+ handler.reset(new related_posts(handler, report.HANDLED(related_all)));
+
+ // anonymize_posts removes all meaningful information from xact payee's and
+ // account names, for the sake of creating useful bug reports.
+ if (report.HANDLED(anon))
+ handler.reset(new anonymize_posts(handler));
+
+ // This filter_posts will only pass through posts matching the `predicate'.
+ if (report.HANDLED(limit_)) {
+ DEBUG("report.predicate",
+ "Report predicate expression = " << report.HANDLER(limit_).str());
+ handler.reset(new filter_posts
+ (handler, predicate_t(report.HANDLER(limit_).str(),
+ report.what_to_keep()),
+ report));
+ }
+
+ // budget_posts takes a set of posts from a data file and uses them to
+ // generate "budget posts" which balance against the reported posts.
+ //
+ // forecast_posts is a lot like budget_posts, except that it adds xacts
+ // only for the future, and does not balance them against anything but the
+ // future balance.
+
+ if (report.budget_flags != BUDGET_NO_BUDGET) {
+ budget_posts * budget_handler = new budget_posts(handler,
+ report.budget_flags);
+ budget_handler->add_period_xacts(report.session.journal->period_xacts);
+ handler.reset(budget_handler);
+
+ // Apply this before the budget handler, so that only matching posts are
+ // calculated toward the budget. The use of filter_posts above will
+ // further clean the results so that no automated posts that don't match
+ // the filter get reported.
+ if (report.HANDLED(limit_))
+ handler.reset(new filter_posts
+ (handler, predicate_t(report.HANDLER(limit_).str(),
+ report.what_to_keep()),
+ report));
+ }
+ else if (report.HANDLED(forecast_while_)) {
+ forecast_posts * forecast_handler
+ = new forecast_posts(handler,
+ predicate_t(report.HANDLER(forecast_while_).str(),
+ report.what_to_keep()),
+ report,
+ report.HANDLED(forecast_years_) ?
+ static_cast<std::size_t>
+ (report.HANDLER(forecast_years_).value.to_long()) :
+ 5UL);
+ forecast_handler->add_period_xacts(report.session.journal->period_xacts);
+ handler.reset(forecast_handler);
+
+ // See above, under budget_posts.
+ if (report.HANDLED(limit_))
+ handler.reset(new filter_posts
+ (handler, predicate_t(report.HANDLER(limit_).str(),
+ report.what_to_keep()),
+ report));
+ }
+
+ return handler;
+}
+
+} // namespace ledger
diff --git a/src/chain.h b/src/chain.h
new file mode 100644
index 00000000..a2b75b3a
--- /dev/null
+++ b/src/chain.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup report
+ */
+
+/**
+ * @file chain.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _CHAIN_H
+#define _CHAIN_H
+
+#include "utils.h"
+
+namespace ledger {
+
+class post_t;
+class account_t;
+
+template <typename T>
+struct item_handler : public noncopyable
+{
+ shared_ptr<item_handler> handler;
+
+public:
+ item_handler() {
+ TRACE_CTOR(item_handler, "");
+ }
+ item_handler(shared_ptr<item_handler> _handler) : handler(_handler) {
+ TRACE_CTOR(item_handler, "shared_ptr<item_handler>");
+ }
+ virtual ~item_handler() {
+ TRACE_DTOR(item_handler);
+ }
+
+ virtual void flush() {
+ if (handler.get())
+ handler->flush();
+ }
+ virtual void operator()(T& item) {
+ if (handler.get()) {
+ check_for_signal();
+ (*handler.get())(item);
+ }
+ }
+};
+
+typedef shared_ptr<item_handler<post_t> > post_handler_ptr;
+typedef shared_ptr<item_handler<account_t> > acct_handler_ptr;
+
+class report_t;
+post_handler_ptr
+chain_post_handlers(report_t& report,
+ post_handler_ptr base_handler,
+ bool for_accounts_report = false);
+
+} // namespace ledger
+
+#endif // _CHAIN_H
diff --git a/src/commodity.cc b/src/commodity.cc
new file mode 100644
index 00000000..79ed77fe
--- /dev/null
+++ b/src/commodity.cc
@@ -0,0 +1,705 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "amount.h"
+#include "commodity.h"
+#include "annotate.h"
+#include "pool.h"
+
+namespace ledger {
+
+bool commodity_t::european_by_default = false;
+
+void commodity_t::history_t::add_price(commodity_t& source,
+ const datetime_t& date,
+ const amount_t& price,
+ const bool reflexive)
+{
+ DEBUG("commodity.prices.add", "add_price to " << source
+ << (reflexive ? " (secondary)" : " (primary)")
+ << " : " << date << ", " << price);
+
+ history_map::iterator i = prices.find(date);
+ if (i != prices.end()) {
+ (*i).second = price;
+ } else {
+ std::pair<history_map::iterator, bool> result
+ = prices.insert(history_map::value_type(date, price));
+ assert(result.second);
+ }
+
+ if (reflexive) {
+ amount_t inverse = price.inverted();
+ inverse.set_commodity(const_cast<commodity_t&>(source));
+ price.commodity().add_price(date, inverse, false);
+ } else {
+ DEBUG("commodity.prices.add",
+ "marking commodity " << source.symbol() << " as primary");
+ source.add_flags(COMMODITY_PRIMARY);
+ }
+}
+
+bool commodity_t::history_t::remove_price(const datetime_t& date)
+{
+ DEBUG("commodity.prices.add", "remove_price: " << date);
+
+ history_map::size_type n = prices.erase(date);
+ if (n > 0)
+ return true;
+ return false;
+}
+
+void commodity_t::varied_history_t::
+ add_price(commodity_t& source,
+ const datetime_t& date,
+ const amount_t& price,
+ const bool reflexive)
+{
+ optional<history_t&> hist = history(price.commodity());
+ if (! hist) {
+ std::pair<history_by_commodity_map::iterator, bool> result
+ = histories.insert(history_by_commodity_map::value_type
+ (&price.commodity(), history_t()));
+ assert(result.second);
+
+ hist = (*result.first).second;
+ }
+ assert(hist);
+
+ hist->add_price(source, date, price, reflexive);
+}
+
+bool commodity_t::varied_history_t::remove_price(const datetime_t& date,
+ commodity_t& comm)
+{
+ DEBUG("commodity.prices.add", "varied_remove_price: " << date << ", " << comm);
+
+ if (optional<history_t&> hist = history(comm))
+ return hist->remove_price(date);
+ return false;
+}
+
+optional<price_point_t>
+commodity_t::history_t::find_price(const optional<datetime_t>& moment,
+ const optional<datetime_t>& oldest
+#if defined(DEBUG_ON)
+ , const int indent
+#endif
+ ) const
+{
+ price_point_t point;
+ bool found = false;
+
+#define DEBUG_INDENT(cat, indent) \
+ do { \
+ if (SHOW_DEBUG(cat)) \
+ for (int i = 0; i < indent; i++) \
+ ledger::_log_buffer << " "; \
+ } while (false)
+
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent);
+ if (moment)
+ DEBUG("commodity.prices.find", "find price nearest before or on: " << *moment);
+ else
+ DEBUG("commodity.prices.find", "find any price");
+
+ if (oldest) {
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find", " but no older than: " << *oldest);
+ }
+#endif
+
+ if (prices.size() == 0) {
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find", " there are no prices in this history");
+#endif
+ return none;
+ }
+
+ if (! moment) {
+ history_map::const_reverse_iterator r = prices.rbegin();
+ point.when = (*r).first;
+ point.price = (*r).second;
+ found = true;
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find", " using most recent price");
+#endif
+ } else {
+ history_map::const_iterator i = prices.lower_bound(*moment);
+ if (i == prices.end()) {
+ history_map::const_reverse_iterator r = prices.rbegin();
+ point.when = (*r).first;
+ point.price = (*r).second;
+ found = true;
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find", " using last price");
+#endif
+ } else {
+ point.when = (*i).first;
+ if (*moment < point.when) {
+ if (i != prices.begin()) {
+ --i;
+ point.when = (*i).first;
+ point.price = (*i).second;
+ found = true;
+ }
+ } else {
+ point.price = (*i).second;
+ found = true;
+ }
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find", " using found price");
+#endif
+ }
+ }
+
+ if (! found) {
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find", " could not find a price");
+#endif
+ return none;
+ }
+ else if (moment && point.when > *moment) {
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find", " price is too young ");
+#endif
+ return none;
+ }
+ else if (oldest && point.when < *oldest) {
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find", " price is too old ");
+#endif
+ return none;
+ }
+ else {
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find",
+ " returning price: " << point.when << ", " << point.price);
+#endif
+ return point;
+ }
+}
+
+optional<price_point_t>
+commodity_t::varied_history_t::find_price(const commodity_t& source,
+ const optional<commodity_t&>& commodity,
+ const optional<datetime_t>& moment,
+ const optional<datetime_t>& oldest
+#if defined(DEBUG_ON)
+ , const int indent
+#endif
+ ) const
+{
+ optional<price_point_t> point;
+ optional<datetime_t> limit = oldest;
+
+ assert(! commodity || source != *commodity);
+
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find", "varied_find_price for: " << source);
+
+ DEBUG_INDENT("commodity.prices.find", indent);
+ if (commodity)
+ DEBUG("commodity.prices.find", " looking for: commodity '" << *commodity << "'");
+ else
+ DEBUG("commodity.prices.find", " looking for: any commodity");
+
+ if (moment) {
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find", " time index: " << *moment);
+ }
+
+ if (oldest) {
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find", " only consider prices younger than: " << *oldest);
+ }
+#endif
+
+ // Either we couldn't find a history for the target commodity, or we
+ // couldn't find a price. In either case, search all histories known
+ // to this commodity for a price which we can calculate in terms of
+ // the goal commodity.
+ price_point_t best;
+ bool found = false;
+
+ foreach (history_by_commodity_map::value_type hist, histories) {
+ commodity_t& comm(*hist.first);
+ if (comm == source)
+ continue;
+
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent + 1);
+ DEBUG("commodity.prices.find",
+ " searching for price via commodity '" << comm << "'");
+#endif
+
+ point = hist.second.find_price(moment, limit
+#if defined(DEBUG_ON)
+ , indent + 2
+#endif
+ );
+ assert(! point || point->price.commodity() == comm);
+
+ if (point) {
+ optional<price_point_t> xlat;
+
+ if (commodity && comm != *commodity) {
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent + 1);
+ DEBUG("commodity.prices.find", " looking for translation price");
+#endif
+
+ xlat = comm.find_price(commodity, moment, limit
+#if defined(DEBUG_ON)
+ , indent + 2
+#endif
+ );
+ if (xlat) {
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent + 1);
+ DEBUG("commodity.prices.find", " found translated price "
+ << xlat->price << " from " << xlat->when);
+#endif
+
+ point->price = xlat->price * point->price;
+ if (xlat->when < point->when) {
+ point->when = xlat->when;
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent + 1);
+ DEBUG("commodity.prices.find",
+ " adjusting date of result back to " << point->when);
+#endif
+ }
+ } else {
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent + 1);
+ DEBUG("commodity.prices.find", " saw no translated price there");
+#endif
+ continue;
+ }
+ }
+
+ assert(! commodity || point->price.commodity() == *commodity);
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent + 1);
+ DEBUG("commodity.prices.find",
+ " saw a price there: " << point->price << " from " << point->when);
+#endif
+ if (! limit || point->when > *limit) {
+ limit = point->when;
+ best = *point;
+ found = true;
+ }
+ } else {
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent + 1);
+ DEBUG("commodity.prices.find", " saw no price there");
+#endif
+ }
+ }
+
+ if (found) {
+#if defined(DEBUG_ON)
+ DEBUG_INDENT("commodity.prices.find", indent);
+ DEBUG("commodity.prices.find",
+ " found price " << best.price << " from " << best.when);
+ DEBUG("commodity.download",
+ "found price " << best.price << " from " << best.when);
+#endif
+ return best;
+ }
+ return none;
+}
+
+optional<commodity_t::history_t&>
+commodity_t::varied_history_t::history(const optional<commodity_t&>& commodity)
+{
+ commodity_t * comm = NULL;
+ if (! commodity) {
+ if (histories.size() > 1)
+ return none;
+ comm = (*histories.begin()).first;
+ } else {
+ comm = &(*commodity);
+ }
+
+ history_by_commodity_map::iterator i = histories.find(comm);
+ if (i != histories.end())
+ return (*i).second;
+
+ return none;
+}
+
+optional<price_point_t>
+commodity_t::check_for_updated_price(const optional<price_point_t>& point,
+ const optional<datetime_t>& moment,
+ const optional<commodity_t&>& in_terms_of)
+{
+ if (pool().get_quotes && ! has_flags(COMMODITY_NOMARKET)) {
+ bool exceeds_leeway = true;
+
+ if (point) {
+ time_duration_t::sec_type seconds_diff;
+ if (moment) {
+ seconds_diff = (*moment - point->when).total_seconds();
+ DEBUG("commodity.download", "moment = " << *moment);
+ DEBUG("commodity.download", "slip.moment = " << seconds_diff);
+ } else {
+ seconds_diff = (TRUE_CURRENT_TIME() - point->when).total_seconds();
+ DEBUG("commodity.download", "slip.now = " << seconds_diff);
+ }
+
+ DEBUG("commodity.download", "leeway = " << pool().quote_leeway);
+ if (seconds_diff < pool().quote_leeway)
+ exceeds_leeway = false;
+ }
+
+ if (exceeds_leeway) {
+ DEBUG("commodity.download",
+ "attempting to download a more current quote...");
+ if (optional<price_point_t> quote =
+ pool().get_commodity_quote(*this, in_terms_of)) {
+ if (! in_terms_of ||
+ (quote->price.has_commodity() &&
+ quote->price.commodity() == *in_terms_of))
+ return quote;
+ }
+ }
+ }
+ return point;
+}
+
+commodity_t::operator bool() const
+{
+ return this != pool().null_commodity;
+}
+
+bool commodity_t::symbol_needs_quotes(const string& symbol)
+{
+ foreach (char ch, symbol)
+ if (std::isspace(ch) || std::isdigit(ch) || ch == '-' || ch == '.')
+ return true;
+
+ return false;
+}
+
+namespace {
+ bool is_reserved_token(const char * buf)
+ {
+ switch (buf[0]) {
+ case 'a':
+ return std::strcmp(buf, "and") == 0;
+ case 'd':
+ return std::strcmp(buf, "div") == 0;
+ case 'e':
+ return std::strcmp(buf, "else") == 0;
+ case 'f':
+ return std::strcmp(buf, "false") == 0;
+ case 'i':
+ return std::strcmp(buf, "if") == 0;
+ case 'o':
+ return std::strcmp(buf, "or") == 0;
+ case 'n':
+ return std::strcmp(buf, "not") == 0;
+ case 't':
+ return std::strcmp(buf, "true") == 0;
+ }
+ return false;
+ }
+}
+
+void commodity_t::parse_symbol(std::istream& in, string& symbol)
+{
+ // Invalid commodity characters:
+ // SPACE, TAB, NEWLINE, RETURN
+ // 0-9 . , ; - + * / ^ ? : & | ! =
+ // < > { } [ ] ( ) @
+
+ static int invalid_chars[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
+ /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 20 */ 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 40 */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
+ /* 60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* a0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* b0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* c0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* d0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* e0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* f0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+ istream_pos_type pos = in.tellg();
+
+ char buf[256];
+ char c = peek_next_nonws(in);
+ if (c == '"') {
+ in.get(c);
+ READ_INTO(in, buf, 255, c, c != '"');
+ if (c == '"')
+ in.get(c);
+ else
+ throw_(amount_error, _("Quoted commodity symbol lacks closing quote"));
+ } else {
+ char * _p = buf;
+ c = static_cast<char>(in.peek());
+ while (_p - buf < 255 && in.good() && ! in.eof() && c != '\n') {
+ std::size_t bytes = 0;
+ std::ptrdiff_t size = _p - buf;
+ unsigned char d = c;
+
+ // Check for the start of a UTF-8 multi-byte encoded string
+ if (d >= 192 && d <= 223 && size < 254)
+ bytes = 2;
+ else if (d >= 224 && d <= 239 && size < 253)
+ bytes = 3;
+ else if (d >= 240 && d <= 247 && size < 252)
+ bytes = 4;
+ else if (d >= 248 && d <= 251 && size < 251)
+ bytes = 5;
+ else if (d >= 252 && d <= 253 && size < 250)
+ bytes = 6;
+ else if (d >= 254) // UTF-8 encoding error
+ break;
+
+ if (bytes > 0) { // we're looking at a UTF-8 encoding
+ for (std::size_t i = 0; i < bytes; i++) {
+ in.get(c);
+ if (in.bad() || in.eof())
+ throw_(amount_error, _("Invalid UTF-8 encoding for commodity name"));
+ *_p++ = c;
+ }
+ }
+ else if (invalid_chars[static_cast<unsigned char>(c)]) {
+ break;
+ }
+ else {
+ in.get(c);
+ if (in.eof())
+ break;
+ if (c == '\\') {
+ in.get(c);
+ if (in.eof())
+ throw_(amount_error, _("Backslash at end of commodity name"));
+ }
+ *_p++ = c;
+ }
+
+ c = static_cast<char>(in.peek());
+ }
+ *_p = '\0';
+
+ if (is_reserved_token(buf))
+ buf[0] = '\0';
+ }
+ symbol = buf;
+
+ if (symbol.length() == 0) {
+ in.clear();
+ in.seekg(pos, std::ios::beg);
+ }
+}
+
+void commodity_t::parse_symbol(char *& p, string& symbol)
+{
+ if (*p == '"') {
+ char * q = std::strchr(p + 1, '"');
+ if (! q)
+ throw_(amount_error, _("Quoted commodity symbol lacks closing quote"));
+ symbol = string(p + 1, 0, q - p - 1);
+ p = q + 2;
+ } else {
+ char * q = next_element(p);
+ symbol = p;
+ if (q)
+ p = q;
+ else
+ p += symbol.length();
+ }
+ if (symbol.empty())
+ throw_(amount_error, _("Failed to parse commodity"));
+}
+
+bool commodity_t::valid() const
+{
+ if (symbol().empty() && this != pool().null_commodity) {
+ DEBUG("ledger.validate",
+ "commodity_t: symbol().empty() && this != null_commodity");
+ return false;
+ }
+
+ if (annotated && ! base) {
+ DEBUG("ledger.validate", "commodity_t: annotated && ! base");
+ return false;
+ }
+
+ if (precision() > 16) {
+ DEBUG("ledger.validate", "commodity_t: precision() > 16");
+ return false;
+ }
+
+ return true;
+}
+
+bool compare_amount_commodities::operator()(const amount_t * left,
+ const amount_t * right) const
+{
+ commodity_t& leftcomm(left->commodity());
+ commodity_t& rightcomm(right->commodity());
+
+ DEBUG("commodity.compare", " left symbol (" << leftcomm << ")");
+ DEBUG("commodity.compare", "right symbol (" << rightcomm << ")");
+
+ int cmp = leftcomm.base_symbol().compare(rightcomm.base_symbol());
+ if (cmp != 0)
+ return cmp < 0;
+
+ if (! leftcomm.has_annotation()) {
+ return rightcomm.has_annotation();
+ }
+ else if (! rightcomm.has_annotation()) {
+ return ! leftcomm.has_annotation();
+ }
+ else {
+ annotated_commodity_t& aleftcomm(static_cast<annotated_commodity_t&>(leftcomm));
+ annotated_commodity_t& arightcomm(static_cast<annotated_commodity_t&>(rightcomm));
+
+ if (! aleftcomm.details.price && arightcomm.details.price)
+ return true;
+ if (aleftcomm.details.price && ! arightcomm.details.price)
+ return false;
+
+ if (aleftcomm.details.price && arightcomm.details.price) {
+ amount_t leftprice(*aleftcomm.details.price);
+ amount_t rightprice(*arightcomm.details.price);
+
+ if (leftprice.commodity() == rightprice.commodity()) {
+ return (leftprice - rightprice).sign() < 0;
+ } else {
+ // Since we have two different amounts, there's really no way
+ // to establish a true sorting order; we'll just do it based
+ // on the numerical values.
+ leftprice.clear_commodity();
+ rightprice.clear_commodity();
+ return (leftprice - rightprice).sign() < 0;
+ }
+ }
+
+ if (! aleftcomm.details.date && arightcomm.details.date)
+ return true;
+ if (aleftcomm.details.date && ! arightcomm.details.date)
+ return false;
+
+ if (aleftcomm.details.date && arightcomm.details.date) {
+ gregorian::date_duration diff =
+ *aleftcomm.details.date - *arightcomm.details.date;
+ return diff.is_negative();
+ }
+
+ if (! aleftcomm.details.tag && arightcomm.details.tag)
+ return true;
+ if (aleftcomm.details.tag && ! arightcomm.details.tag)
+ return false;
+
+ if (aleftcomm.details.tag && arightcomm.details.tag)
+ return *aleftcomm.details.tag < *arightcomm.details.tag;
+
+ assert(false);
+ return true;
+ }
+}
+
+void to_xml(std::ostream& out, const commodity_t& comm,
+ bool commodity_details)
+{
+ push_xml x(out, "commodity", true);
+
+ out << " flags=\"";
+ if (! (comm.has_flags(COMMODITY_STYLE_SUFFIXED))) out << 'P';
+ if (comm.has_flags(COMMODITY_STYLE_SEPARATED)) out << 'S';
+ if (comm.has_flags(COMMODITY_STYLE_THOUSANDS)) out << 'T';
+ if (comm.has_flags(COMMODITY_STYLE_EUROPEAN)) out << 'E';
+ out << '"';
+
+ x.close_attrs();
+
+ {
+ push_xml y(out, "symbol");
+ out << y.guard(comm.symbol());
+ }
+
+ if (commodity_details) {
+ if (comm.has_annotation())
+ to_xml(out, as_annotated_commodity(comm).details);
+
+ if (comm.varied_history()) {
+ push_xml y(out, "varied-history");
+
+ foreach (const commodity_t::history_by_commodity_map::value_type& pair,
+ comm.varied_history()->histories) {
+ {
+ push_xml z(out, "symbol");
+ out << y.guard(pair.first->symbol());
+ }
+ {
+ push_xml z(out, "history");
+
+ foreach (const commodity_t::history_map::value_type& inner_pair,
+ pair.second.prices) {
+ push_xml w(out, "price-point");
+ to_xml(out, inner_pair.first);
+ to_xml(out, inner_pair.second);
+ }
+ }
+ }
+ }
+ }
+}
+
+} // namespace ledger
diff --git a/src/commodity.h b/src/commodity.h
new file mode 100644
index 00000000..3370f3f2
--- /dev/null
+++ b/src/commodity.h
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup math
+ */
+
+/**
+ * @file commodity.h
+ * @author John Wiegley
+ *
+ * @ingroup math
+ *
+ * @brief Types for handling commodities
+ *
+ * This file contains one of the most basic types in Ledger:
+ * commodity_t, and its annotated cousin, annotated_commodity_t.
+ */
+#ifndef _COMMODITY_H
+#define _COMMODITY_H
+
+namespace ledger {
+
+class keep_details_t;
+
+DECLARE_EXCEPTION(commodity_error, std::runtime_error);
+
+struct price_point_t
+{
+ datetime_t when;
+ amount_t price;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & when;
+ ar & price;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class commodity_t
+ : public delegates_flags<uint_least16_t>,
+ public equality_comparable1<commodity_t, noncopyable>
+{
+public:
+ typedef std::map<const datetime_t, amount_t> history_map;
+
+ struct history_t
+ {
+ history_map prices;
+
+ void add_price(commodity_t& source,
+ const datetime_t& date,
+ const amount_t& price,
+ const bool reflexive = true);
+ bool remove_price(const datetime_t& date);
+
+ optional<price_point_t>
+ find_price(const optional<datetime_t>& moment = none,
+ const optional<datetime_t>& oldest = none
+#if defined(DEBUG_ON)
+ , const int indent = 0
+#endif
+ ) const;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+ private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & prices;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+ };
+
+ typedef std::map<commodity_t *, history_t> history_by_commodity_map;
+
+ struct varied_history_t
+ {
+ history_by_commodity_map histories;
+
+ void add_price(commodity_t& source,
+ const datetime_t& date,
+ const amount_t& price,
+ const bool reflexive = true);
+ bool remove_price(const datetime_t& date, commodity_t& commodity);
+
+ optional<price_point_t>
+ find_price(const commodity_t& source,
+ const optional<commodity_t&>& commodity = none,
+ const optional<datetime_t>& moment = none,
+ const optional<datetime_t>& oldest = none
+#if defined(DEBUG_ON)
+ , const int indent = 0
+#endif
+ ) const;
+
+ optional<history_t&>
+ history(const optional<commodity_t&>& commodity = none);
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+ private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & histories;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+ };
+
+protected:
+ friend class commodity_pool_t;
+ friend class annotated_commodity_t;
+
+ class base_t : public noncopyable, public supports_flags<uint_least16_t>
+ {
+ public:
+#define COMMODITY_STYLE_DEFAULTS 0x000
+#define COMMODITY_STYLE_SUFFIXED 0x001
+#define COMMODITY_STYLE_SEPARATED 0x002
+#define COMMODITY_STYLE_EUROPEAN 0x004
+#define COMMODITY_STYLE_THOUSANDS 0x008
+#define COMMODITY_NOMARKET 0x010
+#define COMMODITY_BUILTIN 0x020
+#define COMMODITY_WALKED 0x040
+#define COMMODITY_KNOWN 0x080
+#define COMMODITY_PRIMARY 0x100
+
+ string symbol;
+ amount_t::precision_t precision;
+ optional<string> name;
+ optional<string> note;
+ optional<varied_history_t> varied_history;
+ optional<amount_t> smaller;
+ optional<amount_t> larger;
+
+ mutable bool searched;
+
+ public:
+ explicit base_t(const string& _symbol)
+ : supports_flags<uint_least16_t>
+ (commodity_t::european_by_default ?
+ static_cast<uint_least16_t>(COMMODITY_STYLE_EUROPEAN) :
+ static_cast<uint_least16_t>(COMMODITY_STYLE_DEFAULTS)),
+ symbol(_symbol), precision(0), searched(false) {
+ TRACE_CTOR(base_t, "const string&");
+ }
+ virtual ~base_t() {
+ TRACE_DTOR(base_t);
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+ private:
+ base_t() {
+ TRACE_CTOR(base_t, "");
+ }
+
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<supports_flags<uint_least16_t> >(*this);
+ ar & symbol;
+ ar & precision;
+ ar & name;
+ ar & note;
+ ar & varied_history;
+ ar & smaller;
+ ar & larger;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+ };
+
+ shared_ptr<base_t> base;
+
+ commodity_pool_t * parent_;
+ optional<string> qualified_symbol;
+ optional<string> mapping_key_;
+ bool annotated;
+
+ explicit commodity_t(commodity_pool_t * _parent,
+ const shared_ptr<base_t>& _base)
+ : delegates_flags<uint_least16_t>(*_base.get()), base(_base),
+ parent_(_parent), annotated(false) {
+ TRACE_CTOR(commodity_t, "commodity_pool_t *, shared_ptr<base_t>");
+ }
+
+public:
+ static bool european_by_default;
+
+ virtual ~commodity_t() {
+ TRACE_DTOR(commodity_t);
+ }
+
+ operator bool() const;
+
+ virtual bool operator==(const commodity_t& comm) const {
+ if (comm.annotated)
+ return comm == *this;
+ return base.get() == comm.base.get();
+ }
+
+ static bool symbol_needs_quotes(const string& symbol);
+
+ virtual commodity_t& referent() {
+ return *this;
+ }
+ virtual const commodity_t& referent() const {
+ return *this;
+ }
+
+ bool has_annotation() const {
+ return annotated;
+ }
+
+ virtual commodity_t& strip_annotations(const keep_details_t&) {
+ return *this;
+ }
+ virtual void write_annotations(std::ostream&) const {}
+
+ commodity_pool_t& pool() const {
+ return *parent_;
+ }
+
+ string base_symbol() const {
+ return base->symbol;
+ }
+ string symbol() const {
+ return qualified_symbol ? *qualified_symbol : base_symbol();
+ }
+
+ string mapping_key() const {
+ if (mapping_key_)
+ return *mapping_key_;
+ else
+ return base_symbol();
+ }
+
+ optional<string> name() const {
+ return base->name;
+ }
+ void set_name(const optional<string>& arg = none) {
+ base->name = arg;
+ }
+
+ optional<string> note() const {
+ return base->note;
+ }
+ void set_note(const optional<string>& arg = none) {
+ base->note = arg;
+ }
+
+ amount_t::precision_t precision() const {
+ return base->precision;
+ }
+ void set_precision(amount_t::precision_t arg) {
+ base->precision = arg;
+ }
+
+ optional<amount_t> smaller() const {
+ return base->smaller;
+ }
+ void set_smaller(const optional<amount_t>& arg = none) {
+ base->smaller = arg;
+ }
+
+ optional<amount_t> larger() const {
+ return base->larger;
+ }
+ void set_larger(const optional<amount_t>& arg = none) {
+ base->larger = arg;
+ }
+
+ optional<varied_history_t&> varied_history() {
+ if (base->varied_history)
+ return *base->varied_history;
+ return none;
+ }
+ optional<const varied_history_t&> varied_history() const {
+ if (base->varied_history)
+ return *base->varied_history;
+ return none;
+ }
+
+ optional<history_t&> history(const optional<commodity_t&>& commodity);
+
+ // These methods provide a transparent pass-through to the underlying
+ // base->varied_history object.
+
+ void add_price(const datetime_t& date, const amount_t& price,
+ const bool reflexive = true) {
+ if (! base->varied_history)
+ base->varied_history = varied_history_t();
+
+ base->varied_history->add_price(*this, date, price, reflexive);
+ }
+ bool remove_price(const datetime_t& date, commodity_t& commodity) {
+ if (base->varied_history)
+ base->varied_history->remove_price(date, commodity);
+ return false;
+ }
+
+ optional<price_point_t>
+ find_price(const optional<commodity_t&>& commodity = none,
+ const optional<datetime_t>& moment = none,
+ const optional<datetime_t>& oldest = none
+#if defined(DEBUG_ON)
+ , const int indent = 0
+#endif
+ ) const {
+ if (base->varied_history && ! has_flags(COMMODITY_WALKED)) {
+ const_cast<commodity_t&>(*this).add_flags(COMMODITY_WALKED);
+ optional<price_point_t> point =
+ base->varied_history->find_price(*this, commodity, moment, oldest
+#if defined(DEBUG_ON)
+ , indent
+#endif
+ );
+ const_cast<commodity_t&>(*this).drop_flags(COMMODITY_WALKED);
+ return point;
+ }
+ return none;
+ }
+
+ optional<price_point_t>
+ check_for_updated_price(const optional<price_point_t>& point,
+ const optional<datetime_t>& moment,
+ const optional<commodity_t&>& in_terms_of);
+
+ // Methods related to parsing, reading, writing, etc., the commodity
+ // itself.
+
+ static void parse_symbol(std::istream& in, string& symbol);
+ static void parse_symbol(char *& p, string& symbol);
+ static string parse_symbol(std::istream& in) {
+ string temp;
+ parse_symbol(in, temp);
+ return temp;
+ }
+
+ void print(std::ostream& out) const {
+ out << symbol();
+ }
+
+ bool valid() const;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ supports_flags<uint_least16_t> temp_flags;
+
+protected:
+ explicit commodity_t()
+ : delegates_flags<uint_least16_t>(temp_flags), parent_(NULL),
+ annotated(false) {
+ TRACE_CTOR(commodity_t, "");
+ }
+
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<delegates_flags<uint_least16_t> >(*this);
+ ar & base;
+ ar & parent_;
+ ar & qualified_symbol;
+ ar & mapping_key_;
+ ar & annotated;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+inline std::ostream& operator<<(std::ostream& out, const commodity_t& comm) {
+ comm.print(out);
+ return out;
+}
+
+struct compare_amount_commodities {
+ bool operator()(const amount_t * left, const amount_t * right) const;
+};
+
+void to_xml(std::ostream& out, const commodity_t& comm,
+ bool commodity_details = false);
+
+} // namespace ledger
+
+#endif // _COMMODITY_H
diff --git a/src/compare.cc b/src/compare.cc
new file mode 100644
index 00000000..36884a46
--- /dev/null
+++ b/src/compare.cc
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "compare.h"
+#include "op.h"
+#include "post.h"
+#include "account.h"
+
+namespace ledger {
+
+void push_sort_value(std::list<sort_value_t>& sort_values,
+ expr_t::ptr_op_t node, scope_t& scope)
+{
+ if (node->kind == expr_t::op_t::O_CONS) {
+ push_sort_value(sort_values, node->left(), scope);
+ push_sort_value(sort_values, node->right(), scope);
+ } else {
+ bool inverted = false;
+
+ if (node->kind == expr_t::op_t::O_NEG) {
+ inverted = true;
+ node = node->left();
+ }
+
+ sort_values.push_back(sort_value_t());
+ sort_values.back().inverted = inverted;
+ sort_values.back().value = expr_t(node).calc(scope).simplified();
+
+ if (sort_values.back().value.is_null())
+ throw_(calc_error,
+ _("Could not determine sorting value based an expression"));
+ }
+}
+
+template <>
+bool compare_items<post_t>::operator()(post_t * left, post_t * right)
+{
+ assert(left);
+ assert(right);
+
+ post_t::xdata_t& lxdata(left->xdata());
+ if (! lxdata.has_flags(POST_EXT_SORT_CALC)) {
+ bind_scope_t bound_scope(*sort_order.get_context(), *left);
+ find_sort_values(lxdata.sort_values, bound_scope);
+ lxdata.add_flags(POST_EXT_SORT_CALC);
+ }
+
+ post_t::xdata_t& rxdata(right->xdata());
+ if (! rxdata.has_flags(POST_EXT_SORT_CALC)) {
+ bind_scope_t bound_scope(*sort_order.get_context(), *right);
+ find_sort_values(rxdata.sort_values, bound_scope);
+ rxdata.add_flags(POST_EXT_SORT_CALC);
+ }
+
+ return sort_value_is_less_than(lxdata.sort_values, rxdata.sort_values);
+}
+
+template <>
+bool compare_items<account_t>::operator()(account_t * left, account_t * right)
+{
+ assert(left);
+ assert(right);
+
+ account_t::xdata_t& lxdata(left->xdata());
+ if (! lxdata.has_flags(ACCOUNT_EXT_SORT_CALC)) {
+ bind_scope_t bound_scope(*sort_order.get_context(), *left);
+ find_sort_values(lxdata.sort_values, bound_scope);
+ lxdata.add_flags(ACCOUNT_EXT_SORT_CALC);
+ }
+
+ account_t::xdata_t& rxdata(right->xdata());
+ if (! rxdata.has_flags(ACCOUNT_EXT_SORT_CALC)) {
+ bind_scope_t bound_scope(*sort_order.get_context(), *right);
+ find_sort_values(rxdata.sort_values, bound_scope);
+ rxdata.add_flags(ACCOUNT_EXT_SORT_CALC);
+ }
+
+ DEBUG("value.sort", "Comparing accounts " << left->fullname()
+ << " <> " << right->fullname());
+
+ return sort_value_is_less_than(lxdata.sort_values, rxdata.sort_values);
+}
+
+} // namespace ledger
diff --git a/src/compare.h b/src/compare.h
new file mode 100644
index 00000000..740ba275
--- /dev/null
+++ b/src/compare.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup data
+ */
+
+/**
+ * @file compare.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _COMPARE_H
+#define _COMPARE_H
+
+#include "expr.h"
+
+namespace ledger {
+
+class post_t;
+class account_t;
+
+void push_sort_value(std::list<sort_value_t>& sort_values,
+ expr_t::ptr_op_t node, scope_t& scope);
+
+template <typename T>
+class compare_items
+{
+ expr_t sort_order;
+
+ compare_items();
+
+public:
+ compare_items(const compare_items& other) : sort_order(other.sort_order) {
+ TRACE_CTOR(compare_items, "copy");
+ }
+ compare_items(const expr_t& _sort_order) : sort_order(_sort_order) {
+ TRACE_CTOR(compare_items, "const value_expr&");
+ }
+ ~compare_items() throw() {
+ TRACE_DTOR(compare_items);
+ }
+
+ void find_sort_values(std::list<sort_value_t>& sort_values, scope_t& scope) {
+ push_sort_value(sort_values, sort_order.get_op(), scope);
+ }
+
+ bool operator()(T * left, T * right);
+};
+
+sort_value_t calc_sort_value(const expr_t::ptr_op_t op);
+
+template <typename T>
+bool compare_items<T>::operator()(T * left, T * right)
+{
+ assert(left); assert(right);
+ return sort_value_is_less_than(find_sort_values(left),
+ find_sort_values(right));
+}
+
+template <>
+bool compare_items<post_t>::operator()(post_t * left, post_t * right);
+template <>
+bool compare_items<account_t>::operator()(account_t * left,
+ account_t * right);
+
+} // namespace ledger
+
+#endif // _COMPARE_H
diff --git a/src/draft.cc b/src/draft.cc
new file mode 100644
index 00000000..8478a31d
--- /dev/null
+++ b/src/draft.cc
@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "draft.h"
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "journal.h"
+#include "session.h"
+#include "report.h"
+#include "output.h"
+
+namespace ledger {
+
+void draft_t::xact_template_t::dump(std::ostream& out) const
+{
+ if (date)
+ out << _("Date: ") << *date << std::endl;
+ else
+ out << _("Date: <today>") << std::endl;
+
+ if (code)
+ out << _("Code: ") << *code << std::endl;
+ if (note)
+ out << _("Note: ") << *note << std::endl;
+
+ if (payee_mask.empty())
+ out << _("Payee mask: INVALID (template expression will cause an error)")
+ << std::endl;
+ else
+ out << _("Payee mask: ") << payee_mask << std::endl;
+
+ if (posts.empty()) {
+ out << std::endl
+ << _("<Posting copied from last related transaction>")
+ << std::endl;
+ } else {
+ bool has_only_from = true;
+ bool has_only_to = true;
+
+ foreach (const post_template_t& post, posts) {
+ if (post.from)
+ has_only_to = false;
+ else
+ has_only_from = false;
+ }
+
+ foreach (const post_template_t& post, posts) {
+ straccstream accum;
+ out << std::endl
+ << ACCUM(accum << _("[Posting \"%1\"]")
+ << (post.from ? _("from") : _("to")))
+ << std::endl;
+
+ if (post.account_mask)
+ out << _(" Account mask: ") << *post.account_mask << std::endl;
+ else if (post.from)
+ out << _(" Account mask: <use last of last related accounts>") << std::endl;
+ else
+ out << _(" Account mask: <use first of last related accounts>") << std::endl;
+
+ if (post.amount)
+ out << _(" Amount: ") << *post.amount << std::endl;
+
+ if (post.cost)
+ out << _(" Cost: ") << *post.cost_operator
+ << " " << *post.cost << std::endl;
+ }
+ }
+}
+
+void draft_t::parse_args(const value_t& args)
+{
+ regex date_mask(_("([0-9]+(?:[-/.][0-9]+)?(?:[-/.][0-9]+))?"));
+ smatch what;
+ bool check_for_date = true;
+
+ tmpl = xact_template_t();
+
+ optional<date_time::weekdays> weekday;
+ xact_template_t::post_template_t * post = NULL;
+
+ value_t::sequence_t::const_iterator begin = args.begin();
+ value_t::sequence_t::const_iterator end = args.end();
+
+ for (; begin != end; begin++) {
+ if (check_for_date &&
+ regex_match((*begin).to_string(), what, date_mask)) {
+ tmpl->date = parse_date(what[0]);
+ check_for_date = false;
+ }
+ else if (check_for_date &&
+ bool(weekday = string_to_day_of_week(what[0]))) {
+ short dow = static_cast<short>(*weekday);
+ date_t date = CURRENT_DATE() - date_duration(1);
+ while (date.day_of_week() != dow)
+ date -= date_duration(1);
+ tmpl->date = date;
+ check_for_date = false;
+ }
+ else {
+ string arg = (*begin).to_string();
+
+ if (arg == "at") {
+ if (begin == end)
+ throw std::runtime_error(_("Invalid xact command arguments"));
+ tmpl->payee_mask = (*++begin).to_string();
+ }
+ else if (arg == "to" || arg == "from") {
+ if (! post || post->account_mask) {
+ tmpl->posts.push_back(xact_template_t::post_template_t());
+ post = &tmpl->posts.back();
+ }
+ if (begin == end)
+ throw std::runtime_error(_("Invalid xact command arguments"));
+ post->account_mask = mask_t((*++begin).to_string());
+ post->from = arg == "from";
+ }
+ else if (arg == "on") {
+ if (begin == end)
+ throw std::runtime_error(_("Invalid xact command arguments"));
+ tmpl->date = parse_date((*++begin).to_string());
+ check_for_date = false;
+ }
+ else if (arg == "code") {
+ if (begin == end)
+ throw std::runtime_error(_("Invalid xact command arguments"));
+ tmpl->code = (*++begin).to_string();
+ }
+ else if (arg == "note") {
+ if (begin == end)
+ throw std::runtime_error(_("Invalid xact command arguments"));
+ tmpl->note = (*++begin).to_string();
+ }
+ else if (arg == "rest") {
+ ; // just ignore this argument
+ }
+ else if (arg == "@" || arg == "@@") {
+ amount_t cost;
+ post->cost_operator = arg;
+ if (begin == end)
+ throw std::runtime_error(_("Invalid xact command arguments"));
+ arg = (*++begin).to_string();
+ if (! cost.parse(arg, PARSE_SOFT_FAIL | PARSE_NO_MIGRATE))
+ throw std::runtime_error(_("Invalid xact command arguments"));
+ post->cost = cost;
+ }
+ else {
+ // Without a preposition, it is either:
+ //
+ // A payee, if we have not seen one
+ // An account or an amount, if we have
+ // An account if an amount has just been seen
+ // An amount if an account has just been seen
+
+ if (tmpl->payee_mask.empty()) {
+ tmpl->payee_mask = arg;
+ }
+ else {
+ amount_t amt;
+ optional<mask_t> account;
+
+ if (! amt.parse(arg, PARSE_SOFT_FAIL | PARSE_NO_MIGRATE))
+ account = mask_t(arg);
+
+ if (! post ||
+ (account && post->account_mask) ||
+ (! account && post->amount)) {
+ tmpl->posts.push_back(xact_template_t::post_template_t());
+ post = &tmpl->posts.back();
+ }
+
+ if (account) {
+ post->from = false;
+ post->account_mask = account;
+ } else {
+ post->amount = amt;
+ }
+ }
+ }
+ }
+ }
+
+ if (! tmpl->posts.empty()) {
+ bool has_only_from = true;
+ bool has_only_to = true;
+
+ // A single account at the end of the line is the "from" account
+ if (tmpl->posts.size() > 1 &&
+ tmpl->posts.back().account_mask && ! tmpl->posts.back().amount)
+ tmpl->posts.back().from = true;
+
+ foreach (xact_template_t::post_template_t& post, tmpl->posts) {
+ if (post.from)
+ has_only_to = false;
+ else
+ has_only_from = false;
+ }
+
+ if (has_only_from) {
+ tmpl->posts.push_front(xact_template_t::post_template_t());
+ }
+ else if (has_only_to) {
+ tmpl->posts.push_back(xact_template_t::post_template_t());
+ tmpl->posts.back().from = true;
+ }
+ }
+}
+
+xact_t * draft_t::insert(journal_t& journal)
+{
+ if (tmpl->payee_mask.empty())
+ throw std::runtime_error(_("xact' command requires at least a payee"));
+
+ xact_t * matching = NULL;
+
+ std::auto_ptr<xact_t> added(new xact_t);
+
+ for (xacts_list::reverse_iterator j = journal.xacts.rbegin();
+ j != journal.xacts.rend();
+ j++) {
+ if (tmpl->payee_mask.match((*j)->payee)) {
+ matching = *j;
+ DEBUG("derive.xact",
+ "Found payee match: transaction on line " << (*j)->pos->beg_line);
+ break;
+ }
+ }
+
+ if (! tmpl->date) {
+ added->_date = CURRENT_DATE();
+ DEBUG("derive.xact", "Setting date to current date");
+ } else {
+ added->_date = tmpl->date;
+ DEBUG("derive.xact", "Setting date to template date: " << *tmpl->date);
+ }
+
+ added->set_state(item_t::UNCLEARED);
+
+ if (matching) {
+ added->payee = matching->payee;
+ added->code = matching->code;
+ added->note = matching->note;
+
+#if defined(DEBUG_ON)
+ DEBUG("derive.xact", "Setting payee from match: " << added->payee);
+ if (added->code)
+ DEBUG("derive.xact", "Setting code from match: " << *added->code);
+ if (added->note)
+ DEBUG("derive.xact", "Setting note from match: " << *added->note);
+#endif
+ } else {
+ added->payee = tmpl->payee_mask.str();
+ DEBUG("derive.xact", "Setting payee from template: " << added->payee);
+ }
+
+ if (tmpl->code) {
+ added->code = tmpl->code;
+ DEBUG("derive.xact", "Now setting code from template: " << *added->code);
+ }
+ if (tmpl->note) {
+ added->note = tmpl->note;
+ DEBUG("derive.xact", "Now setting note from template: " << *added->note);
+ }
+
+ if (tmpl->posts.empty()) {
+ if (matching) {
+ DEBUG("derive.xact", "Template had no postings, copying from match");
+
+ foreach (post_t * post, matching->posts) {
+ added->add_post(new post_t(*post));
+ added->posts.back()->set_state(item_t::UNCLEARED);
+ }
+ } else {
+ throw_(std::runtime_error,
+ _("No accounts, and no past transaction matching '%1'")
+ << tmpl->payee_mask);
+ }
+ } else {
+ DEBUG("derive.xact", "Template had postings");
+
+ bool any_post_has_amount = false;
+ foreach (xact_template_t::post_template_t& post, tmpl->posts) {
+ if (post.amount) {
+ DEBUG("derive.xact", " and at least one has an amount specified");
+ any_post_has_amount = true;
+ break;
+ }
+ }
+
+ foreach (xact_template_t::post_template_t& post, tmpl->posts) {
+ std::auto_ptr<post_t> new_post;
+
+ commodity_t * found_commodity = NULL;
+
+ if (matching) {
+ if (post.account_mask) {
+ DEBUG("derive.xact",
+ "Looking for matching posting based on account mask");
+
+ foreach (post_t * x, matching->posts) {
+ if (post.account_mask->match(x->account->fullname())) {
+ new_post.reset(new post_t(*x));
+ DEBUG("derive.xact",
+ "Founding posting from line " << x->pos->beg_line);
+ break;
+ }
+ }
+ } else {
+ if (post.from) {
+ for (posts_list::reverse_iterator j = matching->posts.rbegin();
+ j != matching->posts.rend();
+ j++) {
+ if ((*j)->must_balance()) {
+ new_post.reset(new post_t(**j));
+ DEBUG("derive.xact",
+ "Copied last real posting from matching");
+ break;
+ }
+ }
+ } else {
+ for (posts_list::iterator j = matching->posts.begin();
+ j != matching->posts.end();
+ j++) {
+ if ((*j)->must_balance()) {
+ new_post.reset(new post_t(**j));
+ DEBUG("derive.xact",
+ "Copied first real posting from matching");
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (! new_post.get()) {
+ new_post.reset(new post_t);
+ DEBUG("derive.xact", "New posting was NULL, creating a blank one");
+ }
+
+ if (! new_post->account) {
+ DEBUG("derive.xact", "New posting still needs an account");
+
+ if (post.account_mask) {
+ DEBUG("derive.xact", "The template has an account mask");
+
+ account_t * acct = NULL;
+ if (! acct) {
+ acct = journal.find_account_re(post.account_mask->str());
+#if defined(DEBUG_ON)
+ if (acct)
+ DEBUG("derive.xact", "Found account as a regular expression");
+#endif
+ }
+ if (! acct) {
+ acct = journal.find_account(post.account_mask->str());
+#if defined(DEBUG_ON)
+ if (acct)
+ DEBUG("derive.xact", "Found (or created) account by name");
+#endif
+ }
+
+ // Find out the default commodity to use by looking at the last
+ // commodity used in that account
+ for (xacts_list::reverse_iterator j = journal.xacts.rbegin();
+ j != journal.xacts.rend();
+ j++) {
+ foreach (post_t * x, (*j)->posts) {
+ if (x->account == acct && ! x->amount.is_null()) {
+ new_post.reset(new post_t(*x));
+ DEBUG("derive.xact",
+ "Found account in journal postings, setting new posting");
+ break;
+ }
+ }
+ }
+
+ new_post->account = acct;
+ DEBUG("derive.xact",
+ "Set new posting's account to: " << acct->fullname());
+ } else {
+ if (post.from) {
+ new_post->account = journal.find_account(_("Liabilities:Unknown"));
+ DEBUG("derive.xact",
+ "Set new posting's account to: Liabilities:Unknown");
+ } else {
+ new_post->account = journal.find_account(_("Expenses:Unknown"));
+ DEBUG("derive.xact",
+ "Set new posting's account to: Expenses:Unknown");
+ }
+ }
+ }
+ assert(new_post->account);
+
+ if (new_post.get() && ! new_post->amount.is_null()) {
+ found_commodity = &new_post->amount.commodity();
+
+ if (any_post_has_amount) {
+ new_post->amount = amount_t();
+ DEBUG("derive.xact", "New posting has an amount, but we cleared it");
+ } else {
+ any_post_has_amount = true;
+ DEBUG("derive.xact", "New posting has an amount, and we're using it");
+ }
+ }
+
+ if (post.amount) {
+ new_post->amount = *post.amount;
+ DEBUG("derive.xact", "Copied over posting amount");
+
+ if (post.from) {
+ new_post->amount.in_place_negate();
+ DEBUG("derive.xact", "Negated new posting amount");
+ }
+ }
+
+ if (post.cost) {
+ if (post.cost->sign() < 0)
+ throw parse_error(_("A posting's cost may not be negative"));
+
+ post.cost->in_place_unround();
+
+ if (*post.cost_operator == "@") {
+ // For the sole case where the cost might be uncommoditized,
+ // guarantee that the commodity of the cost after multiplication
+ // is the same as it was before.
+ commodity_t& cost_commodity(post.cost->commodity());
+ *post.cost *= new_post->amount;
+ post.cost->set_commodity(cost_commodity);
+ }
+
+ new_post->cost = *post.cost;
+ DEBUG("derive.xact", "Copied over posting cost");
+ }
+
+ if (found_commodity &&
+ ! new_post->amount.is_null() &&
+ ! new_post->amount.has_commodity()) {
+ new_post->amount.set_commodity(*found_commodity);
+ DEBUG("derive.xact", "Set posting amount commodity to: "
+ << new_post->amount.commodity());
+
+ new_post->amount = new_post->amount.rounded();
+ DEBUG("derive.xact",
+ "Rounded posting amount to: " << new_post->amount);
+ }
+
+ added->add_post(new_post.release());
+ added->posts.back()->account->add_post(added->posts.back());
+ added->posts.back()->set_state(item_t::UNCLEARED);
+
+ DEBUG("derive.xact", "Added new posting to derived entry");
+ }
+ }
+
+ if (! journal.add_xact(added.get()))
+ throw_(std::runtime_error,
+ _("Failed to finalize derived transaction (check commodities)"));
+
+ return added.release();
+}
+
+value_t template_command(call_scope_t& args)
+{
+ report_t& report(find_scope<report_t>(args));
+ std::ostream& out(report.output_stream);
+
+ out << _("--- Input arguments ---") << std::endl;
+ args.value().dump(out);
+ out << std::endl << std::endl;
+
+ draft_t draft(args.value());
+
+ out << _("--- Transaction template ---") << std::endl;
+ draft.dump(out);
+
+ return true;
+}
+
+value_t xact_command(call_scope_t& args)
+{
+ report_t& report(find_scope<report_t>(args));
+ draft_t draft(args.value());
+
+ xact_t * new_xact = draft.insert(*report.session.journal.get());
+
+ // Only consider actual postings for the "xact" command
+ report.HANDLER(limit_).on(string("#xact"), "actual");
+
+ report.xact_report(post_handler_ptr
+ (new format_posts(report,
+ report.HANDLER(print_format_).str())),
+ *new_xact);
+ return true;
+}
+
+} // namespace ledger
diff --git a/src/draft.h b/src/draft.h
new file mode 100644
index 00000000..93e98ff5
--- /dev/null
+++ b/src/draft.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup expr
+ */
+
+/**
+ * @file draft.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _DRAFT_H
+#define _DRAFT_H
+
+#include "exprbase.h"
+#include "value.h"
+
+namespace ledger {
+
+class journal_t;
+class xact_t;
+
+class draft_t : public expr_base_t<value_t>
+{
+ typedef expr_base_t<value_t> base_type;
+
+ struct xact_template_t
+ {
+ optional<date_t> date;
+ optional<string> code;
+ optional<string> note;
+ mask_t payee_mask;
+
+ struct post_template_t {
+ bool from;
+ optional<mask_t> account_mask;
+ optional<amount_t> amount;
+ optional<string> cost_operator;
+ optional<amount_t> cost;
+
+ post_template_t() : from(false) {}
+ };
+
+ std::list<post_template_t> posts;
+
+ xact_template_t() {}
+
+ void dump(std::ostream& out) const;
+ };
+
+ optional<xact_template_t> tmpl;
+
+public:
+ draft_t(const value_t& args) : base_type() {
+ TRACE_CTOR(draft_t, "value_t");
+ if (! args.empty())
+ parse_args(args);
+ }
+ virtual ~draft_t() {
+ TRACE_DTOR(draft_t);
+ }
+
+ void parse_args(const value_t& args);
+
+ virtual result_type real_calc(scope_t&) {
+ assert(false);
+ return true;
+ }
+
+ xact_t * insert(journal_t& journal);
+
+ virtual void dump(std::ostream& out) const {
+ if (tmpl)
+ tmpl->dump(out);
+ }
+};
+
+value_t xact_command(call_scope_t& args);
+value_t template_command(call_scope_t& args);
+
+} // namespace ledger
+
+#endif // _DRAFT_H
diff --git a/src/emacs.cc b/src/emacs.cc
new file mode 100644
index 00000000..dc1a18ae
--- /dev/null
+++ b/src/emacs.cc
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "emacs.h"
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+
+namespace ledger {
+
+void format_emacs_posts::write_xact(xact_t& xact)
+{
+ out << "\"" << xact.pos->pathname << "\" "
+ << xact.pos->beg_line << " ";
+
+ tm when = gregorian::to_tm(xact.date());
+ std::time_t date = std::mktime(&when);
+
+ out << "(" << (date / 65536) << " " << (date % 65536) << " 0) ";
+
+ if (! xact.code)
+ out << "nil ";
+ else
+ out << "\"" << *xact.code << "\" ";
+
+ if (xact.payee.empty())
+ out << "nil";
+ else
+ out << "\"" << xact.payee << "\"";
+
+ out << "\n";
+}
+
+void format_emacs_posts::operator()(post_t& post)
+{
+ if (! post.has_xdata() ||
+ ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
+ if (! last_xact) {
+ out << "((";
+ write_xact(*post.xact);
+ }
+ else if (post.xact != last_xact) {
+ out << ")\n (";
+ write_xact(*post.xact);
+ }
+ else {
+ out << "\n";
+ }
+
+ out << " (" << post.pos->beg_line << " ";
+ out << "\"" << post.reported_account()->fullname() << "\" \""
+ << post.amount << "\"";
+
+ switch (post.state()) {
+ case item_t::CLEARED:
+ out << " t";
+ break;
+ case item_t::PENDING:
+ out << " pending";
+ break;
+ default:
+ out << " nil";
+ break;
+ }
+
+ if (post.cost)
+ out << " \"" << *post.cost << "\"";
+ if (post.note)
+ out << " \"" << *post.note << "\"";
+ out << ")";
+
+ last_xact = post.xact;
+
+ post.xdata().add_flags(POST_EXT_DISPLAYED);
+ }
+}
+
+} // namespace ledger
diff --git a/src/emacs.h b/src/emacs.h
new file mode 100644
index 00000000..4b2a452a
--- /dev/null
+++ b/src/emacs.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup report
+ */
+
+/**
+ * @file emacs.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _EMACS_H
+#define _EMACS_H
+
+#include "chain.h"
+
+namespace ledger {
+
+class xact_t;
+
+class format_emacs_posts : public item_handler<post_t>
+{
+ format_emacs_posts();
+
+protected:
+ std::ostream& out;
+ xact_t * last_xact;
+
+public:
+ format_emacs_posts(std::ostream& _out)
+ : out(_out), last_xact(NULL) {
+ TRACE_CTOR(format_emacs_posts, "std::ostream&");
+ }
+ ~format_emacs_posts() {
+ TRACE_DTOR(format_emacs_posts);
+ }
+
+ virtual void write_xact(xact_t& xact);
+ virtual void flush() {
+ if (last_xact)
+ out << "))\n";
+ out.flush();
+ }
+ virtual void operator()(post_t& post);
+};
+
+} // namespace ledger
+
+#endif // _REPORT_H
diff --git a/src/error.cc b/src/error.cc
new file mode 100644
index 00000000..d5abe4de
--- /dev/null
+++ b/src/error.cc
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "utils.h"
+
+namespace ledger {
+
+straccstream _ctxt_accum;
+std::ostringstream _ctxt_buffer;
+straccstream _desc_accum;
+std::ostringstream _desc_buffer;
+
+string error_context()
+{
+ string context = _ctxt_buffer.str();
+ _ctxt_buffer.str("");
+ return context;
+}
+
+string file_context(const path& file, const std::size_t line)
+{
+ std::ostringstream buf;
+ buf << "\"" << file << "\", line " << line << ": ";
+ return buf.str();
+}
+
+string line_context(const string& line,
+ const string::size_type pos,
+ const string::size_type end_pos)
+{
+ std::ostringstream buf;
+ buf << " " << line << "\n";
+
+ if (pos != 0) {
+ buf << " ";
+ if (end_pos == 0) {
+ for (string::size_type i = 0; i < pos; i += 1)
+ buf << " ";
+ buf << "^";
+ } else {
+ for (string::size_type i = 0; i < end_pos; i += 1) {
+ if (i >= pos)
+ buf << "^";
+ else
+ buf << " ";
+ }
+ }
+ }
+ return buf.str();
+}
+
+string source_context(const path& file,
+ const istream_pos_type pos,
+ const istream_pos_type end_pos,
+ const string& prefix)
+{
+ const std::streamoff len = end_pos - pos;
+ if (! len || file == path("/dev/stdin"))
+ return _("<no source context>");
+
+ assert(len > 0);
+ assert(len < 2048);
+
+ std::ostringstream out;
+
+ ifstream in(file);
+ in.seekg(pos, std::ios::beg);
+
+ scoped_array<char> buf(new char[static_cast<std::size_t>(len) + 1]);
+ in.read(buf.get(), static_cast<std::streamsize>(len));
+ assert(in.gcount() == static_cast<std::streamsize>(len));
+ buf[static_cast<std::size_t>(len)] = '\0';
+
+ bool first = true;
+ for (char * p = std::strtok(buf.get(), "\n");
+ p;
+ p = std::strtok(NULL, "\n")) {
+ if (first)
+ first = false;
+ else
+ out << '\n';
+ out << prefix << p;
+ }
+
+ return out.str();
+}
+
+} // namespace ledger
diff --git a/src/error.h b/src/error.h
new file mode 100644
index 00000000..5369faf1
--- /dev/null
+++ b/src/error.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup util
+ */
+
+/**
+ * @file error.h
+ * @author John Wiegley
+ *
+ * @ingroup util
+ */
+#ifndef _ERROR_H
+#define _ERROR_H
+
+#include "accum.h"
+
+namespace ledger {
+
+extern straccstream _desc_accum;
+extern std::ostringstream _desc_buffer;
+
+template <typename T>
+inline void throw_func(const string& message) {
+ _desc_buffer.str("");
+ throw T(message);
+}
+
+#define throw_(cls, msg) \
+ ((_desc_buffer << ACCUM(_desc_accum << msg)), \
+ _desc_accum.clear(), \
+ throw_func<cls>(_desc_buffer.str()))
+
+inline void warning_func(const string& message) {
+ std::cerr << "Warning: " << message << std::endl;
+ _desc_buffer.str("");
+}
+
+#define warning_(msg) \
+ ((_desc_buffer << ACCUM(_desc_accum << msg)), \
+ _desc_accum.clear(), \
+ warning_func(_desc_buffer.str()))
+
+extern straccstream _ctxt_accum;
+extern std::ostringstream _ctxt_buffer;
+
+#define add_error_context(msg) \
+ ((long(_ctxt_buffer.tellp()) == 0) ? \
+ ((_ctxt_buffer << ACCUM(_ctxt_accum << msg)), \
+ _ctxt_accum.clear()) : \
+ ((_ctxt_buffer << std::endl << ACCUM(_ctxt_accum << msg)), \
+ _ctxt_accum.clear()))
+
+string error_context();
+
+string file_context(const path& file, std::size_t line);
+string line_context(const string& line,
+ const string::size_type pos = 0,
+ const string::size_type end_pos = 0);
+
+string source_context(const path& file,
+ const istream_pos_type pos,
+ const istream_pos_type end_pos,
+ const string& prefix = "");
+
+#define DECLARE_EXCEPTION(name, kind) \
+ class name : public kind { \
+ public: \
+ explicit name(const string& why) throw() : kind(why) {} \
+ virtual ~name() throw() {} \
+ }
+
+} // namespace ledger
+
+#endif // _ERROR_H
diff --git a/src/expr.cc b/src/expr.cc
new file mode 100644
index 00000000..c59f8a57
--- /dev/null
+++ b/src/expr.cc
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "expr.h"
+#include "parser.h"
+
+namespace ledger {
+
+void expr_t::parse(std::istream& in, const parse_flags_t& flags,
+ const optional<string>& original_string)
+{
+ base_type::parse(in, flags, original_string);
+
+ parser_t parser;
+ ptr = parser.parse(in, flags, original_string);
+}
+
+void expr_t::compile(scope_t& scope)
+{
+ if (! compiled && ptr) {
+ ptr = ptr->compile(scope);
+ base_type::compile(scope);
+ }
+}
+
+value_t expr_t::real_calc(scope_t& scope)
+{
+ if (ptr) {
+ ptr_op_t locus;
+ try {
+ return ptr->calc(scope, &locus);
+ }
+ catch (const std::exception& err) {
+ if (locus) {
+ add_error_context(_("While evaluating value expression:"));
+ add_error_context(op_context(ptr, locus));
+
+ if (SHOW_INFO()) {
+ add_error_context(_("The value expression tree was:"));
+ std::ostringstream buf;
+ ptr->dump(buf, 0);
+
+ std::istringstream in(buf.str());
+ std::ostringstream out;
+ char linebuf[1024];
+ bool first = true;
+ while (in.good() && ! in.eof()) {
+ in.getline(linebuf, 1023);
+ std::streamsize len = in.gcount();
+ if (len > 0) {
+ if (first)
+ first = false;
+ else
+ out << '\n';
+ out << " " << linebuf;
+ }
+ }
+ add_error_context(out.str());
+ }
+ }
+ throw;
+ }
+ }
+ return NULL_VALUE;
+}
+
+bool expr_t::is_constant() const
+{
+ assert(compiled);
+ return ptr && ptr->is_value();
+}
+
+bool expr_t::is_function() const
+{
+ assert(compiled);
+ return ptr && ptr->is_function();
+}
+
+value_t& expr_t::constant_value()
+{
+ assert(is_constant());
+ return ptr->as_value_lval();
+}
+
+const value_t& expr_t::constant_value() const
+{
+ assert(is_constant());
+ return ptr->as_value();
+}
+
+expr_t::func_t& expr_t::get_function()
+{
+ assert(is_function());
+ return ptr->as_function_lval();
+}
+
+string expr_t::context_to_str() const
+{
+ return ptr ? op_context(ptr) : _("<empty expression>");
+}
+
+void expr_t::print(std::ostream& out) const
+{
+ if (ptr)
+ ptr->print(out);
+}
+
+void expr_t::dump(std::ostream& out) const
+{
+ if (ptr) ptr->dump(out, 0);
+}
+
+} // namespace ledger
diff --git a/src/expr.h b/src/expr.h
new file mode 100644
index 00000000..638855b1
--- /dev/null
+++ b/src/expr.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup expr
+ */
+
+/**
+ * @file expr.h
+ * @author John Wiegley
+ *
+ * @ingroup expr
+ */
+#ifndef _EXPR_H
+#define _EXPR_H
+
+#include "exprbase.h"
+#include "value.h"
+
+namespace ledger {
+
+class expr_t : public expr_base_t<value_t>
+{
+ struct token_t;
+ class parser_t;
+
+ typedef expr_base_t<value_t> base_type;
+
+public:
+ class op_t;
+ typedef intrusive_ptr<op_t> ptr_op_t;
+ typedef intrusive_ptr<const op_t> const_ptr_op_t;
+
+protected:
+ ptr_op_t ptr;
+
+public:
+ expr_t() : base_type() {
+ TRACE_CTOR(expr_t, "");
+ }
+ expr_t(const expr_t& other)
+ : base_type(other), ptr(other.ptr) {
+ TRACE_CTOR(expr_t, "copy");
+ }
+ expr_t(ptr_op_t _ptr, scope_t * _context = NULL)
+ : base_type(_context), ptr(_ptr) {
+ TRACE_CTOR(expr_t, "const ptr_op_t&, scope_t *");
+ }
+
+ expr_t(const string& _str, const parse_flags_t& flags = PARSE_DEFAULT)
+ : base_type() {
+ TRACE_CTOR(expr_t, "string, parse_flags_t");
+ if (! _str.empty())
+ parse(_str, flags);
+ }
+ expr_t(std::istream& in, const parse_flags_t& flags = PARSE_DEFAULT)
+ : base_type() {
+ TRACE_CTOR(expr_t, "std::istream&, parse_flags_t");
+ parse(in, flags);
+ }
+
+ virtual ~expr_t() {
+ TRACE_DTOR(expr_t);
+ }
+
+ expr_t& operator=(const expr_t& _expr) {
+ if (this != &_expr) {
+ base_type::operator=(_expr);
+ ptr = _expr.ptr;
+ }
+ return *this;
+ }
+
+ virtual operator bool() const throw() {
+ return ptr.get() != NULL;
+ }
+
+ ptr_op_t get_op() throw() {
+ return ptr;
+ }
+
+ void parse(const string& str, const parse_flags_t& flags = PARSE_DEFAULT) {
+ std::istringstream stream(str);
+ return parse(stream, flags, str);
+ }
+
+ virtual void parse(std::istream& in,
+ const parse_flags_t& flags = PARSE_DEFAULT,
+ const optional<string>& original_string = none);
+ virtual void compile(scope_t& scope);
+ virtual value_t real_calc(scope_t& scope);
+
+ bool is_constant() const;
+ value_t& constant_value();
+ const value_t& constant_value() const;
+ bool is_function() const;
+ func_t& get_function();
+
+ virtual string context_to_str() const;
+ virtual void print(std::ostream& out) const;
+ virtual void dump(std::ostream& out) const;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<base_type>(*this);
+ ar & ptr;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+} // namespace ledger
+
+#endif // _EXPR_H
diff --git a/src/exprbase.h b/src/exprbase.h
new file mode 100644
index 00000000..0b3466b0
--- /dev/null
+++ b/src/exprbase.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup expr
+ */
+
+/**
+ * @file exprbase.h
+ * @author John Wiegley
+ *
+ * @ingroup expr
+ *
+ * This class provides basic behavior for all the domain specific expression
+ * languages used in Leger:
+ *
+ * | Typename | Description | result_type | Derives |
+ * |-------------+----------------------------+-----------------+-------------|
+ * | expr_t | Value expressions | value_t | |
+ * | predicate_t | Special form of expr_t | bool | expr_t |
+ * | query_t | Report queries | bool | predicate_t |
+ * | period_t | Time periods and durations | date_interval_t | |
+ * | draft_t | Partially filled xacts | xact_t * | |
+ * | format_t | Format strings | string | |
+ */
+#ifndef _EXPRBASE_H
+#define _EXPRBASE_H
+
+#include "utils.h"
+#include "amount.h"
+
+namespace ledger {
+
+DECLARE_EXCEPTION(parse_error, std::runtime_error);
+DECLARE_EXCEPTION(compile_error, std::runtime_error);
+DECLARE_EXCEPTION(calc_error, std::runtime_error);
+DECLARE_EXCEPTION(usage_error, std::runtime_error);
+
+class scope_t;
+class call_scope_t;
+
+template <typename ResultType>
+class expr_base_t
+{
+public:
+ typedef ResultType result_type;
+
+ typedef function<result_type (call_scope_t&)> func_t;
+
+protected:
+ scope_t * context;
+ string str;
+ bool compiled;
+
+ virtual result_type real_calc(scope_t& scope) = 0;
+
+public:
+ expr_base_t(const expr_base_t& other)
+ : context(other.context), str(other.str), compiled(false) {
+ TRACE_CTOR(expr_base_t, "copy");
+ }
+ expr_base_t(scope_t * _context = NULL)
+ : context(_context), compiled(false)
+ {
+ TRACE_CTOR(expr_base_t, "scope_t *");
+ }
+ virtual ~expr_base_t() {
+ TRACE_DTOR(expr_base_t);
+ }
+
+ expr_base_t& operator=(const expr_base_t& _expr) {
+ if (this != &_expr) {
+ str = _expr.str;
+ context = _expr.context;
+ compiled = _expr.compiled;
+ }
+ return *this;
+ }
+ expr_base_t& operator=(const string& _expr) {
+ parse(_expr);
+ return *this;
+ }
+
+ virtual operator bool() const throw() {
+ return ! str.empty();
+ }
+
+ virtual string text() {
+ return str;
+ }
+ void set_text(const string& txt) {
+ str = txt;
+ compiled = false;
+ }
+
+ void parse(const string& str, const parse_flags_t& flags = PARSE_DEFAULT) {
+ std::istringstream stream(str);
+ return parse(stream, flags, str);
+ }
+ virtual void parse(std::istream&,
+ const parse_flags_t& = PARSE_DEFAULT,
+ const optional<string>& original_string = none) {
+ set_text(original_string ? *original_string : "<stream>");
+ }
+
+ void mark_uncompiled() {
+ compiled = false;
+ }
+
+ void recompile(scope_t& scope) {
+ compiled = false;
+ compile(scope);
+ }
+
+ virtual void compile(scope_t& scope) {
+ if (! compiled) {
+ // Derived classes need to do something here.
+ context = &scope;
+ compiled = true;
+ }
+ }
+
+ result_type operator()(scope_t& scope) {
+ return calc(scope);
+ }
+
+ result_type calc(scope_t& scope)
+ {
+ if (! compiled) {
+ if (SHOW_DEBUG("expr.compile")) {
+ DEBUG("expr.compile", "Before compilation:");
+ dump(*_log_stream);
+ }
+
+ compile(scope);
+
+ if (SHOW_DEBUG("expr.compile")) {
+ DEBUG("expr.compile", "After compilation:");
+ dump(*_log_stream);
+ }
+ }
+
+ return real_calc(scope);
+ }
+
+ result_type calc() {
+ assert(context);
+ return calc(*context);
+ }
+
+ scope_t * get_context() {
+ return context;
+ }
+ void set_context(scope_t * scope) {
+ context = scope;
+ }
+
+ virtual string context_to_str() const {
+ return empty_string;
+ }
+
+ string print_to_str() const {
+ std::ostringstream out;
+ print(out);
+ return out.str();
+ }
+ string dump_to_str() const {
+ std::ostringstream out;
+ dump(out);
+ return out.str();
+ }
+ string preview_to_str(scope_t& scope) const {
+ std::ostringstream out;
+ preview(out);
+ return out.str();
+ }
+
+ virtual void print(std::ostream&) const {}
+ virtual void dump(std::ostream&) const {}
+
+ result_type preview(std::ostream& out, scope_t& scope) const {
+ out << _("--- Input expression ---") << std::endl;
+ out << text() << std::endl;
+
+ out << std::endl << _("--- Text as parsed ---") << std::endl;
+ print(out);
+ out << std::endl;
+
+ out << std::endl << _("--- Expression tree ---") << std::endl;
+ dump(out);
+
+ out << std::endl << _("--- Compiled tree ---") << std::endl;
+ compile(scope);
+ dump(out);
+
+ out << std::endl << _("--- Result value ---") << std::endl;
+ return calc();
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & context;
+ ar & str;
+ if (Archive::is_loading::value)
+ compiled = false;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+template <typename ResultType>
+std::ostream& operator<<(std::ostream& out,
+ const expr_base_t<ResultType>& expr) {
+ expr.print(out);
+ return out;
+}
+
+} // namespace ledger
+
+#endif // _EXPRBASE_H
diff --git a/src/filters.cc b/src/filters.cc
new file mode 100644
index 00000000..0084fac7
--- /dev/null
+++ b/src/filters.cc
@@ -0,0 +1,1055 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "filters.h"
+#include "iterators.h"
+#include "journal.h"
+#include "report.h"
+#include "compare.h"
+
+namespace ledger {
+
+pass_down_posts::pass_down_posts(post_handler_ptr handler,
+ posts_iterator& iter)
+ : item_handler<post_t>(handler)
+{
+ TRACE_CTOR(pass_down_posts, "post_handler_ptr, posts_iterator");
+
+ for (post_t * post = iter(); post; post = iter()) {
+ try {
+ item_handler<post_t>::operator()(*post);
+ }
+ catch (const std::exception& err) {
+ add_error_context(item_context(*post, _("While handling posting")));
+ throw;
+ }
+ }
+
+ item_handler<post_t>::flush();
+}
+
+void truncate_xacts::flush()
+{
+ if (! posts.size())
+ return;
+
+ xact_t * xact = (*posts.begin())->xact;
+
+ int l = 0;
+ foreach (post_t * post, posts)
+ if (xact != post->xact) {
+ l++;
+ xact = post->xact;
+ }
+ l++;
+
+ xact = (*posts.begin())->xact;
+
+ int i = 0;
+ foreach (post_t * post, posts) {
+ if (xact != post->xact) {
+ xact = post->xact;
+ i++;
+ }
+
+ bool print = false;
+ if (head_count) {
+ if (head_count > 0 && i < head_count)
+ print = true;
+ else if (head_count < 0 && i >= - head_count)
+ print = true;
+ }
+
+ if (! print && tail_count) {
+ if (tail_count > 0 && l - i <= tail_count)
+ print = true;
+ else if (tail_count < 0 && l - i > - tail_count)
+ print = true;
+ }
+
+ if (print)
+ item_handler<post_t>::operator()(*post);
+ }
+ posts.clear();
+
+ item_handler<post_t>::flush();
+}
+
+void truncate_xacts::operator()(post_t& post)
+{
+ if (last_xact != post.xact) {
+ if (last_xact)
+ xacts_seen++;
+ last_xact = post.xact;
+ }
+
+ if (tail_count == 0 && head_count > 0 &&
+ static_cast<int>(xacts_seen) >= head_count)
+ return;
+
+ posts.push_back(&post);
+}
+
+void sort_posts::post_accumulated_posts()
+{
+ std::stable_sort(posts.begin(), posts.end(),
+ compare_items<post_t>(sort_order));
+
+ foreach (post_t * post, posts) {
+ post->xdata().drop_flags(POST_EXT_SORT_CALC);
+ item_handler<post_t>::operator()(*post);
+ }
+
+ posts.clear();
+}
+
+namespace {
+ void split_string(const string& str, const char ch,
+ std::list<string>& strings)
+ {
+ const char * b = str.c_str();
+ for (const char * p = b; *p; p++) {
+ if (*p == ch) {
+ strings.push_back(string(b, p - b));
+ b = p + 1;
+ }
+ }
+ strings.push_back(string(b));
+ }
+
+ account_t * create_temp_account_from_path(std::list<string>& account_names,
+ temporaries_t& temps,
+ account_t * master)
+ {
+ account_t * new_account = NULL;
+ foreach (const string& name, account_names) {
+ if (new_account) {
+ new_account = new_account->find_account(name);
+ } else {
+ new_account = master->find_account(name, false);
+ if (! new_account)
+ new_account = &temps.create_account(name, master);
+ }
+ }
+
+ assert(new_account != NULL);
+ return new_account;
+ }
+}
+
+void anonymize_posts::operator()(post_t& post)
+{
+ SHA1 sha;
+ uint_least32_t message_digest[5];
+ bool copy_xact_details = false;
+
+ if (last_xact != post.xact) {
+ temps.copy_xact(*post.xact);
+ last_xact = post.xact;
+ copy_xact_details = true;
+ }
+ xact_t& xact = temps.last_xact();
+
+ if (copy_xact_details) {
+ xact.copy_details(*post.xact);
+
+ sha.Reset();
+ sha << post.xact->payee.c_str();
+ sha.Result(message_digest);
+
+ xact.payee = to_hex(message_digest);
+ xact.note = none;
+ }
+
+ std::list<string> account_names;
+
+ for (account_t * acct = post.account;
+ acct;
+ acct = acct->parent) {
+ sha.Reset();
+ sha << acct->name.c_str();
+ sha.Result(message_digest);
+
+ account_names.push_front(to_hex(message_digest));
+ }
+
+ account_t * new_account =
+ create_temp_account_from_path(account_names, temps, xact.journal->master);
+ post_t& temp = temps.copy_post(post, xact, new_account);
+ temp.note = none;
+
+ (*handler)(temp);
+}
+
+void calc_posts::operator()(post_t& post)
+{
+ post_t::xdata_t& xdata(post.xdata());
+
+ if (last_post) {
+ assert(last_post->has_xdata());
+ if (calc_running_total)
+ xdata.total = last_post->xdata().total;
+ xdata.count = last_post->xdata().count + 1;
+ } else {
+ xdata.count = 1;
+ }
+
+ post.add_to_value(xdata.visited_value, amount_expr);
+ xdata.add_flags(POST_EXT_VISITED);
+
+ account_t * acct = post.reported_account();
+ acct->xdata().add_flags(ACCOUNT_EXT_VISITED);
+
+ if (calc_running_total)
+ add_or_set_value(xdata.total, xdata.visited_value);
+
+ item_handler<post_t>::operator()(post);
+
+ last_post = &post;
+}
+
+namespace {
+ typedef function<void (post_t&)> post_functor_t;
+
+ void handle_value(const value_t& value,
+ account_t * account,
+ xact_t * xact,
+ temporaries_t& temps,
+ post_handler_ptr handler,
+ const date_t& date = date_t(),
+ const value_t& total = value_t(),
+ const bool direct_amount = false,
+ const bool mark_visited = false,
+ const optional<post_functor_t>& functor = none)
+ {
+ post_t& post = temps.create_post(*xact, account);
+ post.add_flags(ITEM_GENERATED);
+
+ // If the account for this post is all virtual, then report the post as
+ // such. This allows subtotal reports to show "(Account)" for accounts
+ // that contain only virtual posts.
+ if (account && account->has_xdata() &&
+ account->xdata().has_flags(ACCOUNT_EXT_AUTO_VIRTUALIZE)) {
+ if (! account->xdata().has_flags(ACCOUNT_EXT_HAS_NON_VIRTUALS)) {
+ post.add_flags(POST_VIRTUAL);
+ if (! account->xdata().has_flags(ACCOUNT_EXT_HAS_UNB_VIRTUALS))
+ post.add_flags(POST_MUST_BALANCE);
+ }
+ }
+
+ post_t::xdata_t& xdata(post.xdata());
+
+ if (is_valid(date))
+ xdata.date = date;
+
+ value_t temp(value);
+
+ switch (value.type()) {
+ case value_t::BOOLEAN:
+ case value_t::INTEGER:
+ temp.in_place_cast(value_t::AMOUNT);
+ // fall through...
+
+ case value_t::AMOUNT:
+ post.amount = temp.as_amount();
+ break;
+
+ case value_t::BALANCE:
+ case value_t::SEQUENCE:
+ xdata.compound_value = temp;
+ xdata.add_flags(POST_EXT_COMPOUND);
+ break;
+
+ case value_t::DATETIME:
+ case value_t::DATE:
+ default:
+ assert(false);
+ break;
+ }
+
+ if (! total.is_null())
+ xdata.total = total;
+
+ if (direct_amount)
+ xdata.add_flags(POST_EXT_DIRECT_AMT);
+
+ if (functor)
+ (*functor)(post);
+
+ DEBUG("filter.changed_value.rounding", "post.amount = " << post.amount);
+
+ (*handler)(post);
+
+ if (mark_visited) {
+ post.xdata().add_flags(POST_EXT_VISITED);
+ post.account->xdata().add_flags(ACCOUNT_EXT_VISITED);
+ }
+ }
+}
+
+void collapse_posts::report_subtotal()
+{
+ if (! count)
+ return;
+
+ std::size_t displayed_count = 0;
+ foreach (post_t * post, component_posts) {
+ if (only_predicate(*post) && display_predicate(*post))
+ displayed_count++;
+ }
+
+ if (displayed_count == 1) {
+ item_handler<post_t>::operator()(*last_post);
+ }
+ else if (only_collapse_if_zero && ! subtotal.is_zero()) {
+ foreach (post_t * post, component_posts)
+ item_handler<post_t>::operator()(*post);
+ }
+ else {
+ date_t earliest_date;
+
+ foreach (post_t * post, component_posts) {
+ date_t reported = post->date();
+ if (! is_valid(earliest_date) ||
+ reported < earliest_date)
+ earliest_date = reported;
+ }
+
+ xact_t& xact = temps.create_xact();
+ xact.payee = last_xact->payee;
+ xact._date = (is_valid(earliest_date) ?
+ earliest_date : last_xact->_date);
+ DEBUG("filter.collapse", "Pseudo-xact date = " << *xact._date);
+
+ handle_value(subtotal, &totals_account, &xact, temps, handler);
+ }
+
+ component_posts.clear();
+
+ last_xact = NULL;
+ last_post = NULL;
+ subtotal = 0L;
+ count = 0;
+}
+
+void collapse_posts::operator()(post_t& post)
+{
+ // If we've reached a new xact, report on the subtotal
+ // accumulated thus far.
+
+ if (last_xact != post.xact && count > 0)
+ report_subtotal();
+
+ post.add_to_value(subtotal, amount_expr);
+
+ component_posts.push_back(&post);
+
+ last_xact = post.xact;
+ last_post = &post;
+ count++;
+}
+
+void related_posts::flush()
+{
+ if (posts.size() > 0) {
+ foreach (post_t * post, posts) {
+ if (post->xact) {
+ foreach (post_t * r_post, post->xact->posts) {
+ post_t::xdata_t& xdata(r_post->xdata());
+ if (! xdata.has_flags(POST_EXT_HANDLED) &&
+ (! xdata.has_flags(POST_EXT_RECEIVED) ?
+ ! r_post->has_flags(ITEM_GENERATED | POST_VIRTUAL) :
+ also_matching)) {
+ xdata.add_flags(POST_EXT_HANDLED);
+ item_handler<post_t>::operator()(*r_post);
+ }
+ }
+ } else {
+ // This code should only be reachable from the "output"
+ // command, since that is the only command which attempts to
+ // output auto or period xacts.
+ post_t::xdata_t& xdata(post->xdata());
+ if (! xdata.has_flags(POST_EXT_HANDLED) &&
+ ! post->has_flags(ITEM_GENERATED)) {
+ xdata.add_flags(POST_EXT_HANDLED);
+ item_handler<post_t>::operator()(*post);
+ }
+ }
+ }
+ }
+
+ item_handler<post_t>::flush();
+}
+
+changed_value_posts::changed_value_posts(post_handler_ptr handler,
+ report_t& _report,
+ bool _for_accounts_report,
+ bool _show_unrealized)
+ : item_handler<post_t>(handler), report(_report),
+ for_accounts_report(_for_accounts_report),
+ show_unrealized(_show_unrealized), last_post(NULL),
+ revalued_account(temps.create_account(_("<Revalued>"))),
+ rounding_account(temps.create_account(_("<Rounding>")))
+{
+ TRACE_CTOR(changed_value_posts, "post_handler_ptr, report_t&, bool");
+
+ display_amount_expr = report.HANDLER(display_amount_).expr;
+ total_expr = (report.HANDLED(revalued_total_) ?
+ report.HANDLER(revalued_total_).expr :
+ report.HANDLER(display_total_).expr);
+ display_total_expr = report.HANDLER(display_total_).expr;
+ changed_values_only = report.HANDLED(revalued_only);
+
+ string gains_equity_account_name;
+ if (report.HANDLED(unrealized_gains_))
+ gains_equity_account_name = report.HANDLER(unrealized_gains_).str();
+ else
+ gains_equity_account_name = _("Equity:Unrealized Gains");
+ gains_equity_account =
+ report.session.journal->master->find_account(gains_equity_account_name);
+ gains_equity_account->add_flags(ACCOUNT_GENERATED);
+
+ string losses_equity_account_name;
+ if (report.HANDLED(unrealized_losses_))
+ losses_equity_account_name = report.HANDLER(unrealized_losses_).str();
+ else
+ losses_equity_account_name = _("Equity:Unrealized Losses");
+ losses_equity_account =
+ report.session.journal->master->find_account(losses_equity_account_name);
+ losses_equity_account->add_flags(ACCOUNT_GENERATED);
+}
+
+void changed_value_posts::flush()
+{
+ if (last_post && last_post->date() <= report.terminus.date()) {
+ output_revaluation(*last_post, report.terminus.date());
+ last_post = NULL;
+ }
+ item_handler<post_t>::flush();
+}
+
+void changed_value_posts::output_revaluation(post_t& post, const date_t& date)
+{
+ if (is_valid(date))
+ post.xdata().date = date;
+
+ value_t repriced_total;
+ try {
+ bind_scope_t bound_scope(report, post);
+ repriced_total = total_expr.calc(bound_scope);
+ }
+ catch (...) {
+ post.xdata().date = date_t();
+ throw;
+ }
+ post.xdata().date = date_t();
+
+ DEBUG("filter.changed_value",
+ "output_revaluation(last_balance) = " << last_total);
+ DEBUG("filter.changed_value",
+ "output_revaluation(repriced_total) = " << repriced_total);
+
+ if (! last_total.is_null()) {
+ if (value_t diff = repriced_total - last_total) {
+ DEBUG("filter.changed_value", "output_revaluation(strip(diff)) = "
+ << diff.strip_annotations(report.what_to_keep()));
+
+ xact_t& xact = temps.create_xact();
+ xact.payee = _("Commodities revalued");
+ xact._date = is_valid(date) ? date : post.date();
+
+ if (! for_accounts_report) {
+ handle_value
+ (/* value= */ diff,
+ /* account= */ &revalued_account,
+ /* xact= */ &xact,
+ /* temps= */ temps,
+ /* handler= */ handler,
+ /* date= */ *xact._date,
+ /* total= */ repriced_total,
+ /* direct_amount= */ false,
+ /* mark_visited= */ false,
+ /* functor= */ (optional<post_functor_t>
+ (bind(&changed_value_posts::output_rounding,
+ this, _1))));
+ }
+ else if (show_unrealized) {
+ handle_value
+ (/* value= */ - diff,
+ /* account= */ (diff < 0L ?
+ losses_equity_account :
+ gains_equity_account),
+ /* xact= */ &xact,
+ /* temps= */ temps,
+ /* handler= */ handler,
+ /* date= */ *xact._date,
+ /* total= */ value_t(),
+ /* direct_amount= */ false,
+ /* mark_visited= */ true);
+ }
+ }
+ }
+}
+
+void changed_value_posts::output_rounding(post_t& post)
+{
+ bind_scope_t bound_scope(report, post);
+ value_t new_display_total(display_total_expr.calc(bound_scope));
+
+ DEBUG("filter.changed_value.rounding",
+ "rounding.new_display_total = " << new_display_total);
+
+ if (! last_display_total.is_null()) {
+ if (value_t repriced_amount = display_amount_expr.calc(bound_scope)) {
+ DEBUG("filter.changed_value.rounding",
+ "rounding.repriced_amount = " << repriced_amount);
+
+ value_t precise_display_total(new_display_total.truncated() -
+ repriced_amount.truncated());
+
+ DEBUG("filter.changed_value.rounding",
+ "rounding.precise_display_total = " << precise_display_total);
+ DEBUG("filter.changed_value.rounding",
+ "rounding.last_display_total = " << last_display_total);
+
+ if (value_t diff = precise_display_total - last_display_total) {
+ DEBUG("filter.changed_value.rounding",
+ "rounding.diff = " << diff);
+
+ xact_t& xact = temps.create_xact();
+ xact.payee = _("Commodity rounding");
+ xact._date = post.date();
+
+ handle_value(diff, &rounding_account, &xact, temps, handler,
+ *xact._date, precise_display_total, true);
+ }
+ }
+ }
+ last_display_total = new_display_total;
+}
+
+void changed_value_posts::operator()(post_t& post)
+{
+ if (last_post)
+ output_revaluation(*last_post, post.date());
+
+ if (changed_values_only)
+ post.xdata().add_flags(POST_EXT_DISPLAYED);
+
+ if (! for_accounts_report)
+ output_rounding(post);
+
+ item_handler<post_t>::operator()(post);
+
+ bind_scope_t bound_scope(report, post);
+ last_total = total_expr.calc(bound_scope);
+ last_post = &post;
+}
+
+void subtotal_posts::report_subtotal(const char * spec_fmt,
+ const optional<date_interval_t>& interval)
+{
+ if (component_posts.empty())
+ return;
+
+ optional<date_t> range_start = interval ? interval->start : none;
+ optional<date_t> range_finish = interval ? interval->inclusive_end() : none;
+
+ if (! range_start || ! range_finish) {
+ foreach (post_t * post, component_posts) {
+ date_t date = post->date();
+ if (! range_start || date < *range_start)
+ range_start = date;
+ if (! range_finish || date > *range_finish)
+ range_finish = date;
+ }
+ }
+ component_posts.clear();
+
+ std::ostringstream out_date;
+ if (spec_fmt) {
+ out_date << format_date(*range_finish, FMT_CUSTOM, spec_fmt);
+ }
+ else if (date_format) {
+ out_date << "- " << format_date(*range_finish, FMT_CUSTOM,
+ date_format->c_str());
+ }
+ else {
+ out_date << "- " << format_date(*range_finish);
+ }
+
+ xact_t& xact = temps.create_xact();
+ xact.payee = out_date.str();
+ xact._date = *range_start;
+
+ foreach (values_map::value_type& pair, values)
+ handle_value(pair.second.value, pair.second.account, &xact, temps,
+ handler);
+
+ values.clear();
+}
+
+void subtotal_posts::operator()(post_t& post)
+{
+ component_posts.push_back(&post);
+
+ account_t * acct = post.reported_account();
+ assert(acct);
+
+ values_map::iterator i = values.find(acct->fullname());
+ if (i == values.end()) {
+ value_t temp;
+ post.add_to_value(temp, amount_expr);
+ std::pair<values_map::iterator, bool> result
+ = values.insert(values_pair(acct->fullname(), acct_value_t(acct, temp)));
+ assert(result.second);
+ } else {
+ post.add_to_value((*i).second.value, amount_expr);
+ }
+
+ // If the account for this post is all virtual, mark it as
+ // such, so that `handle_value' can show "(Account)" for accounts
+ // that contain only virtual posts.
+
+ post.reported_account()->xdata().add_flags(ACCOUNT_EXT_AUTO_VIRTUALIZE);
+
+ if (! post.has_flags(POST_VIRTUAL))
+ post.reported_account()->xdata().add_flags(ACCOUNT_EXT_HAS_NON_VIRTUALS);
+ else if (! post.has_flags(POST_MUST_BALANCE))
+ post.reported_account()->xdata().add_flags(ACCOUNT_EXT_HAS_UNB_VIRTUALS);
+}
+
+void interval_posts::report_subtotal(const date_interval_t& interval)
+{
+ if (last_post && interval) {
+ if (exact_periods)
+ subtotal_posts::report_subtotal();
+ else
+ subtotal_posts::report_subtotal(NULL, interval);
+ }
+
+ last_post = NULL;
+}
+
+void interval_posts::operator()(post_t& post)
+{
+ date_t date = post.date();
+
+ if (! interval.find_period(post.date()))
+ return;
+
+ if (interval.duration) {
+ if (last_interval && interval != last_interval) {
+ report_subtotal(last_interval);
+
+ if (generate_empty_posts) {
+ for (++last_interval; interval != last_interval; ++last_interval) {
+ // Generate a null posting, so the intervening periods can be
+ // seen when -E is used, or if the calculated amount ends up being
+ // non-zero
+ xact_t& null_xact = temps.create_xact();
+ null_xact._date = last_interval.inclusive_end();
+
+ post_t& null_post = temps.create_post(null_xact, &empty_account);
+ null_post.add_flags(POST_CALCULATED);
+ null_post.amount = 0L;
+
+ last_post = &null_post;
+ subtotal_posts::operator()(null_post);
+
+ report_subtotal(last_interval);
+ }
+ assert(interval == last_interval);
+ } else {
+ last_interval = interval;
+ }
+ } else {
+ last_interval = interval;
+ }
+ subtotal_posts::operator()(post);
+ } else {
+ item_handler<post_t>::operator()(post);
+ }
+
+ last_post = &post;
+}
+
+void posts_as_equity::report_subtotal()
+{
+ date_t finish;
+ foreach (post_t * post, component_posts) {
+ date_t date = post->date();
+ if (! is_valid(finish) || date > finish)
+ finish = date;
+ }
+ component_posts.clear();
+
+ xact_t& xact = temps.create_xact();
+ xact.payee = _("Opening Balances");
+ xact._date = finish;
+
+ value_t total = 0L;
+ foreach (values_map::value_type& pair, values) {
+ if (pair.second.value.is_balance()) {
+ foreach (balance_t::amounts_map::value_type amount_pair,
+ pair.second.value.as_balance().amounts)
+ handle_value(amount_pair.second, pair.second.account, &xact, temps,
+ handler);
+ } else {
+ handle_value(pair.second.value, pair.second.account, &xact, temps,
+ handler);
+ }
+ total += pair.second.value;
+ }
+ values.clear();
+
+ if (total.is_balance()) {
+ foreach (balance_t::amounts_map::value_type pair,
+ total.as_balance().amounts) {
+ post_t& balance_post = temps.create_post(xact, balance_account);
+ balance_post.amount = - pair.second;
+ (*handler)(balance_post);
+ }
+ } else {
+ post_t& balance_post = temps.create_post(xact, balance_account);
+ balance_post.amount = - total.to_amount();
+ (*handler)(balance_post);
+ }
+}
+
+void by_payee_posts::flush()
+{
+ foreach (payee_subtotals_map::value_type& pair, payee_subtotals)
+ pair.second->report_subtotal(pair.first.c_str());
+
+ item_handler<post_t>::flush();
+
+ payee_subtotals.clear();
+}
+
+void by_payee_posts::operator()(post_t& post)
+{
+ payee_subtotals_map::iterator i = payee_subtotals.find(post.xact->payee);
+ if (i == payee_subtotals.end()) {
+ payee_subtotals_pair
+ temp(post.xact->payee,
+ shared_ptr<subtotal_posts>(new subtotal_posts(handler, amount_expr)));
+ std::pair<payee_subtotals_map::iterator, bool> result
+ = payee_subtotals.insert(temp);
+
+ assert(result.second);
+ if (! result.second)
+ return;
+ i = result.first;
+ }
+
+ (*(*i).second)(post);
+}
+
+void transfer_details::operator()(post_t& post)
+{
+ xact_t& xact = temps.copy_xact(*post.xact);
+ xact._date = post.date();
+
+ post_t& temp = temps.copy_post(post, xact);
+ temp.set_state(post.state());
+
+ bind_scope_t bound_scope(scope, temp);
+ value_t substitute(expr.calc(bound_scope));
+
+ switch (which_element) {
+ case SET_DATE:
+ temp.xdata().date = substitute.to_date();
+ break;
+
+ case SET_ACCOUNT: {
+ std::list<string> account_names;
+ temp.account->remove_post(&temp);
+ split_string(substitute.to_string(), ':', account_names);
+ temp.account = create_temp_account_from_path(account_names, temps,
+ xact.journal->master);
+ temp.account->add_post(&temp);
+ break;
+ }
+
+ case SET_PAYEE:
+ xact.payee = substitute.to_string();
+ break;
+
+ default:
+ assert(false);
+ break;
+ }
+
+ item_handler<post_t>::operator()(temp);
+}
+
+void dow_posts::flush()
+{
+ for (int i = 0; i < 7; i++) {
+ foreach (post_t * post, days_of_the_week[i])
+ subtotal_posts::operator()(*post);
+ subtotal_posts::report_subtotal("%As");
+ days_of_the_week[i].clear();
+ }
+
+ subtotal_posts::flush();
+}
+
+void generate_posts::add_period_xacts(period_xacts_list& period_xacts)
+{
+ foreach (period_xact_t * xact, period_xacts)
+ foreach (post_t * post, xact->posts)
+ add_post(xact->period, *post);
+}
+
+void generate_posts::add_post(const date_interval_t& period, post_t& post)
+{
+ pending_posts.push_back(pending_posts_pair(period, &post));
+}
+
+void budget_posts::report_budget_items(const date_t& date)
+{
+ if (pending_posts.size() == 0)
+ return;
+
+ bool reported;
+ do {
+ reported = false;
+ foreach (pending_posts_list::value_type& pair, pending_posts) {
+ optional<date_t> begin = pair.first.start;
+ if (! begin) {
+ if (! pair.first.find_period(date))
+ throw_(std::runtime_error, _("Something odd has happened"));
+ begin = pair.first.start;
+ }
+ assert(begin);
+
+ if (*begin <= date &&
+ (! pair.first.finish || *begin < *pair.first.finish)) {
+ post_t& post = *pair.second;
+
+ DEBUG("budget.generate", "Reporting budget for "
+ << post.reported_account()->fullname());
+
+ xact_t& xact = temps.create_xact();
+ xact.payee = _("Budget transaction");
+ xact._date = begin;
+
+ post_t& temp = temps.copy_post(post, xact);
+ temp.amount.in_place_negate();
+
+ if (flags & BUDGET_WRAP_VALUES) {
+ value_t seq;
+ seq.push_back(0L);
+ seq.push_back(temp.amount);
+
+ temp.xdata().compound_value = seq;
+ temp.xdata().add_flags(POST_EXT_COMPOUND);
+ }
+
+ ++pair.first;
+ begin = *pair.first.start;
+
+ item_handler<post_t>::operator()(temp);
+
+ reported = true;
+ }
+ }
+ } while (reported);
+}
+
+void budget_posts::operator()(post_t& post)
+{
+ bool post_in_budget = false;
+
+ foreach (pending_posts_list::value_type& pair, pending_posts) {
+ for (account_t * acct = post.reported_account();
+ acct;
+ acct = acct->parent) {
+ if (acct == (*pair.second).reported_account()) {
+ post_in_budget = true;
+ // Report the post as if it had occurred in the parent account.
+ if (post.reported_account() != acct)
+ post.set_reported_account(acct);
+ goto handle;
+ }
+ }
+ }
+
+ handle:
+ if (post_in_budget && flags & BUDGET_BUDGETED) {
+ report_budget_items(post.date());
+ item_handler<post_t>::operator()(post);
+ }
+ else if (! post_in_budget && flags & BUDGET_UNBUDGETED) {
+ item_handler<post_t>::operator()(post);
+ }
+}
+
+void forecast_posts::add_post(const date_interval_t& period, post_t& post)
+{
+ generate_posts::add_post(period, post);
+
+ // Advance the period's interval until it is at or beyond the current date.
+ date_interval_t& i = pending_posts.back().first;
+ if (! i.start) {
+ if (! i.find_period(CURRENT_DATE()))
+ throw_(std::runtime_error, _("Something odd has happened"));
+ ++i;
+ } else {
+ while (*i.start < CURRENT_DATE())
+ ++i;
+ }
+}
+
+void forecast_posts::flush()
+{
+ posts_list passed;
+ date_t last = CURRENT_DATE();
+
+ // If there are period transactions to apply in a continuing series until
+ // the forecast condition is met, generate those transactions now. Note
+ // that no matter what, we abandon forecasting beyond the next 5 years.
+ //
+ // It works like this:
+ //
+ // Earlier, in forecast_posts::add_period_xacts, we cut up all the periodic
+ // transactions into their components postings, so that we have N "periodic
+ // postings". For example, if the user had this:
+ //
+ // ~ daily
+ // Expenses:Food $10
+ // Expenses:Auto:Gas $20
+ // ~ monthly
+ // Expenses:Food $100
+ // Expenses:Auto:Gas $200
+ //
+ // We now have 4 periodic postings in `pending_posts'.
+ //
+ // Each periodic postings gets its own copy of its parent transaction's
+ // period, which is modified as we go. This is found in the second member
+ // of the pending_posts_list for each posting.
+ //
+ // The algorithm below works by iterating through the N periodic postings
+ // over and over, until each of them mets the termination critera for the
+ // forecast and is removed from the set.
+
+ while (pending_posts.size() > 0) {
+ // At each step through the loop, we find the first periodic posting whose
+ // period contains the earliest starting date.
+ pending_posts_list::iterator least = pending_posts.begin();
+ for (pending_posts_list::iterator i = ++pending_posts.begin();
+ i != pending_posts.end();
+ i++) {
+ if (*(*i).first.start < *(*least).first.start)
+ least = i;
+ }
+
+ date_t& begin = *(*least).first.start;
+ if ((*least).first.finish)
+ assert(begin < *(*least).first.finish);
+
+ // If the next date in the series for this periodic posting is more than 5
+ // years beyond the last valid post we generated, drop it from further
+ // consideration.
+ date_t next = *(*least).first.next;
+ assert(next > begin);
+
+ if (static_cast<std::size_t>((next - last).days()) >
+ static_cast<std::size_t>(365U) * forecast_years) {
+ DEBUG("filters.forecast",
+ "Forecast transaction exceeds " << forecast_years
+ << " years beyond today");
+ pending_posts.erase(least);
+ continue;
+ }
+
+ begin = next;
+ ++(*least).first;
+
+ // `post' refers to the posting defined in the period transaction. We
+ // make a copy of it within a temporary transaction with the payee
+ // "Forecast transaction".
+ post_t& post = *(*least).second;
+ xact_t& xact = temps.create_xact();
+ xact.payee = _("Forecast transaction");
+ xact._date = begin;
+ post_t& temp = temps.copy_post(post, xact);
+
+ // Submit the generated posting
+ DEBUG("filters.forecast",
+ "Forecast transaction: " << temp.date()
+ << " " << temp.account->fullname()
+ << " " << temp.amount);
+ item_handler<post_t>::operator()(temp);
+
+ // If the generated posting matches the user's report query, check whether
+ // it also fails to match the continuation condition for the forecast. If
+ // it does, drop this periodic posting from consideration.
+ if (temp.has_xdata() && temp.xdata().has_flags(POST_EXT_MATCHES)) {
+ DEBUG("filters.forecast", " matches report query");
+ bind_scope_t bound_scope(context, temp);
+ if (! pred(bound_scope)) {
+ DEBUG("filters.forecast", " fails to match continuation criteria");
+ pending_posts.erase(least);
+ continue;
+ }
+ }
+ }
+
+ item_handler<post_t>::flush();
+}
+
+pass_down_accounts::pass_down_accounts(acct_handler_ptr handler,
+ accounts_iterator& iter,
+ const optional<predicate_t>& _pred,
+ const optional<scope_t&>& _context)
+ : item_handler<account_t>(handler), pred(_pred), context(_context)
+{
+ TRACE_CTOR(pass_down_accounts, "acct_handler_ptr, accounts_iterator, ...");
+
+ for (account_t * account = iter(); account; account = iter()) {
+ if (! pred) {
+ item_handler<account_t>::operator()(*account);
+ } else {
+ bind_scope_t bound_scope(*context, *account);
+ if ((*pred)(bound_scope))
+ item_handler<account_t>::operator()(*account);
+ }
+ }
+
+ item_handler<account_t>::flush();
+}
+
+} // namespace ledger
diff --git a/src/filters.h b/src/filters.h
new file mode 100644
index 00000000..92148dbe
--- /dev/null
+++ b/src/filters.h
@@ -0,0 +1,721 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup report
+ */
+
+/**
+ * @file filters.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _FILTERS_H
+#define _FILTERS_H
+
+#include "chain.h"
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "temps.h"
+
+namespace ledger {
+
+//////////////////////////////////////////////////////////////////////
+//
+// Posting filters
+//
+
+class ignore_posts : public item_handler<post_t>
+{
+public:
+ virtual void operator()(post_t&) {}
+};
+
+class collect_posts : public item_handler<post_t>
+{
+public:
+ std::vector<post_t *> posts;
+
+ collect_posts() : item_handler<post_t>() {
+ TRACE_CTOR(collect_posts, "");
+ }
+ virtual ~collect_posts() {
+ TRACE_DTOR(collect_posts);
+ }
+
+ std::size_t length() const {
+ return posts.size();
+ }
+
+ std::vector<post_t *>::iterator begin() {
+ return posts.begin();
+ }
+ std::vector<post_t *>::iterator end() {
+ return posts.end();
+ }
+
+ virtual void flush() {}
+ virtual void operator()(post_t& post) {
+ posts.push_back(&post);
+ }
+};
+
+class posts_iterator;
+
+class pass_down_posts : public item_handler<post_t>
+{
+ pass_down_posts();
+
+public:
+ pass_down_posts(post_handler_ptr handler, posts_iterator& iter);
+
+ virtual ~pass_down_posts() {
+ TRACE_DTOR(pass_down_posts);
+ }
+};
+
+class push_to_posts_list : public item_handler<post_t>
+{
+ push_to_posts_list();
+
+public:
+ posts_list& posts;
+
+ push_to_posts_list(posts_list& _posts) : posts(_posts) {
+ TRACE_CTOR(push_to_posts_list, "posts_list&");
+ }
+ virtual ~push_to_posts_list() {
+ TRACE_DTOR(push_to_posts_list);
+ }
+
+ virtual void operator()(post_t& post) {
+ posts.push_back(&post);
+ }
+};
+
+class truncate_xacts : public item_handler<post_t>
+{
+ int head_count;
+ int tail_count;
+
+ posts_list posts;
+ std::size_t xacts_seen;
+ xact_t * last_xact;
+
+ truncate_xacts();
+
+public:
+ truncate_xacts(post_handler_ptr handler,
+ int _head_count, int _tail_count)
+ : item_handler<post_t>(handler),
+ head_count(_head_count), tail_count(_tail_count),
+ xacts_seen(0), last_xact(NULL) {
+ TRACE_CTOR(truncate_xacts, "post_handler_ptr, int, int");
+ }
+ virtual ~truncate_xacts() {
+ TRACE_DTOR(truncate_xacts);
+ }
+
+ virtual void flush();
+ virtual void operator()(post_t& post);
+};
+
+class sort_posts : public item_handler<post_t>
+{
+ typedef std::deque<post_t *> posts_deque;
+
+ posts_deque posts;
+ const expr_t sort_order;
+
+ sort_posts();
+
+public:
+ sort_posts(post_handler_ptr handler,
+ const expr_t& _sort_order)
+ : item_handler<post_t>(handler),
+ sort_order(_sort_order) {
+ TRACE_CTOR(sort_posts,
+ "post_handler_ptr, const value_expr&");
+ }
+ sort_posts(post_handler_ptr handler,
+ const string& _sort_order)
+ : item_handler<post_t>(handler),
+ sort_order(_sort_order) {
+ TRACE_CTOR(sort_posts,
+ "post_handler_ptr, const string&");
+ }
+ virtual ~sort_posts() {
+ TRACE_DTOR(sort_posts);
+ }
+
+ virtual void post_accumulated_posts();
+
+ virtual void flush() {
+ post_accumulated_posts();
+ item_handler<post_t>::flush();
+ }
+
+ virtual void operator()(post_t& post) {
+ posts.push_back(&post);
+ }
+};
+
+class sort_xacts : public item_handler<post_t>
+{
+ sort_posts sorter;
+ xact_t * last_xact;
+
+ sort_xacts();
+
+public:
+ sort_xacts(post_handler_ptr handler,
+ const expr_t& _sort_order)
+ : sorter(handler, _sort_order) {
+ TRACE_CTOR(sort_xacts,
+ "post_handler_ptr, const value_expr&");
+ }
+ sort_xacts(post_handler_ptr handler,
+ const string& _sort_order)
+ : sorter(handler, _sort_order) {
+ TRACE_CTOR(sort_xacts,
+ "post_handler_ptr, const string&");
+ }
+ virtual ~sort_xacts() {
+ TRACE_DTOR(sort_xacts);
+ }
+
+ virtual void flush() {
+ sorter.flush();
+ item_handler<post_t>::flush();
+ }
+
+ virtual void operator()(post_t& post) {
+ if (last_xact && post.xact != last_xact)
+ sorter.post_accumulated_posts();
+
+ sorter(post);
+
+ last_xact = post.xact;
+ }
+};
+
+class filter_posts : public item_handler<post_t>
+{
+ predicate_t pred;
+ scope_t& context;
+
+ filter_posts();
+
+public:
+ filter_posts(post_handler_ptr handler,
+ const predicate_t& predicate,
+ scope_t& _context)
+ : item_handler<post_t>(handler), pred(predicate), context(_context) {
+ TRACE_CTOR(filter_posts, "post_handler_ptr, predicate_t, scope_t&");
+ }
+ virtual ~filter_posts() {
+ TRACE_DTOR(filter_posts);
+ }
+
+ virtual void operator()(post_t& post) {
+ bind_scope_t bound_scope(context, post);
+ if (pred(bound_scope)) {
+ post.xdata().add_flags(POST_EXT_MATCHES);
+ (*handler)(post);
+ }
+ }
+};
+
+class anonymize_posts : public item_handler<post_t>
+{
+ temporaries_t temps;
+ xact_t * last_xact;
+
+ anonymize_posts();
+
+public:
+ anonymize_posts(post_handler_ptr handler)
+ : item_handler<post_t>(handler), last_xact(NULL) {
+ TRACE_CTOR(anonymize_posts, "post_handler_ptr");
+ }
+ virtual ~anonymize_posts() {
+ TRACE_DTOR(anonymize_posts);
+ }
+
+ virtual void operator()(post_t& post);
+};
+
+class calc_posts : public item_handler<post_t>
+{
+ post_t * last_post;
+ expr_t& amount_expr;
+ bool calc_running_total;
+
+ calc_posts();
+
+public:
+ calc_posts(post_handler_ptr handler,
+ expr_t& _amount_expr,
+ bool _calc_running_total = false)
+ : item_handler<post_t>(handler), last_post(NULL),
+ amount_expr(_amount_expr), calc_running_total(_calc_running_total) {
+ TRACE_CTOR(calc_posts, "post_handler_ptr, expr_t&, bool");
+ }
+ virtual ~calc_posts() {
+ TRACE_DTOR(calc_posts);
+ }
+
+ virtual void operator()(post_t& post);
+};
+
+class collapse_posts : public item_handler<post_t>
+{
+ expr_t& amount_expr;
+ predicate_t display_predicate;
+ predicate_t only_predicate;
+ value_t subtotal;
+ std::size_t count;
+ xact_t * last_xact;
+ post_t * last_post;
+ temporaries_t temps;
+ account_t& totals_account;
+ bool only_collapse_if_zero;
+ std::list<post_t *> component_posts;
+
+ collapse_posts();
+
+public:
+ collapse_posts(post_handler_ptr handler,
+ expr_t& _amount_expr,
+ predicate_t _display_predicate,
+ predicate_t _only_predicate,
+ bool _only_collapse_if_zero = false)
+ : item_handler<post_t>(handler), amount_expr(_amount_expr),
+ display_predicate(_display_predicate),
+ only_predicate(_only_predicate), count(0),
+ last_xact(NULL), last_post(NULL),
+ totals_account(temps.create_account(_("<Total>"))),
+ only_collapse_if_zero(_only_collapse_if_zero) {
+ TRACE_CTOR(collapse_posts, "post_handler_ptr");
+ }
+ virtual ~collapse_posts() {
+ TRACE_DTOR(collapse_posts);
+ }
+
+ virtual void flush() {
+ report_subtotal();
+ item_handler<post_t>::flush();
+ }
+
+ void report_subtotal();
+
+ virtual void operator()(post_t& post);
+};
+
+class related_posts : public item_handler<post_t>
+{
+ posts_list posts;
+ bool also_matching;
+
+ related_posts();
+
+public:
+ related_posts(post_handler_ptr handler,
+ const bool _also_matching = false)
+ : item_handler<post_t>(handler),
+ also_matching(_also_matching) {
+ TRACE_CTOR(related_posts,
+ "post_handler_ptr, const bool");
+ }
+ virtual ~related_posts() throw() {
+ TRACE_DTOR(related_posts);
+ }
+
+ virtual void flush();
+ virtual void operator()(post_t& post) {
+ post.xdata().add_flags(POST_EXT_RECEIVED);
+ posts.push_back(&post);
+ }
+};
+
+class changed_value_posts : public item_handler<post_t>
+{
+ // This filter requires that calc_posts be used at some point
+ // later in the chain.
+
+ expr_t display_amount_expr;
+ expr_t total_expr;
+ expr_t display_total_expr;
+ report_t& report;
+ bool changed_values_only;
+ bool for_accounts_report;
+ bool show_unrealized;
+ post_t * last_post;
+ value_t last_total;
+ value_t last_display_total;
+ temporaries_t temps;
+ account_t& revalued_account;
+ account_t& rounding_account;
+ account_t * gains_equity_account;
+ account_t * losses_equity_account;
+
+ changed_value_posts();
+
+public:
+ changed_value_posts(post_handler_ptr handler,
+ report_t& _report,
+ bool _for_accounts_report,
+ bool _show_unrealized);
+
+ virtual ~changed_value_posts() {
+ TRACE_DTOR(changed_value_posts);
+ }
+
+ virtual void flush();
+
+ void output_revaluation(post_t& post, const date_t& current);
+ void output_rounding(post_t& post);
+
+ virtual void operator()(post_t& post);
+};
+
+class subtotal_posts : public item_handler<post_t>
+{
+ subtotal_posts();
+
+protected:
+ class acct_value_t
+ {
+ acct_value_t();
+
+ public:
+ account_t * account;
+ value_t value;
+
+ acct_value_t(account_t * a) : account(a) {
+ TRACE_CTOR(acct_value_t, "account_t *");
+ }
+ acct_value_t(account_t * a, value_t& v) : account(a), value(v) {
+ TRACE_CTOR(acct_value_t, "account_t *, value_t&");
+ }
+ acct_value_t(const acct_value_t& av)
+ : account(av.account), value(av.value) {
+ TRACE_CTOR(acct_value_t, "copy");
+ }
+ ~acct_value_t() throw() {
+ TRACE_DTOR(acct_value_t);
+ }
+ };
+
+ typedef std::map<string, acct_value_t> values_map;
+ typedef std::pair<string, acct_value_t> values_pair;
+
+protected:
+ expr_t& amount_expr;
+ values_map values;
+ optional<string> date_format;
+ temporaries_t temps;
+ std::list<post_t *> component_posts;
+
+public:
+ subtotal_posts(post_handler_ptr handler, expr_t& _amount_expr,
+ const optional<string>& _date_format = none)
+ : item_handler<post_t>(handler), amount_expr(_amount_expr),
+ date_format(_date_format) {
+ TRACE_CTOR(subtotal_posts,
+ "post_handler_ptr, expr_t&, const optional<string>&");
+ }
+ virtual ~subtotal_posts() {
+ TRACE_DTOR(subtotal_posts);
+ }
+
+ void report_subtotal(const char * spec_fmt = NULL,
+ const optional<date_interval_t>& interval = none);
+
+ virtual void flush() {
+ if (values.size() > 0)
+ report_subtotal();
+ item_handler<post_t>::flush();
+ }
+ virtual void operator()(post_t& post);
+};
+
+class interval_posts : public subtotal_posts
+{
+ date_interval_t interval;
+ date_interval_t last_interval;
+ post_t * last_post;
+ account_t& empty_account;
+ bool exact_periods;
+ bool generate_empty_posts;
+
+ interval_posts();
+
+public:
+
+ interval_posts(post_handler_ptr _handler,
+ expr_t& amount_expr,
+ const date_interval_t& _interval,
+ bool _exact_periods = false,
+ bool _generate_empty_posts = false)
+ : subtotal_posts(_handler, amount_expr), interval(_interval),
+ last_post(NULL), empty_account(temps.create_account(_("<None>"))),
+ exact_periods(_exact_periods),
+ generate_empty_posts(_generate_empty_posts) {
+ TRACE_CTOR(interval_posts,
+ "post_handler_ptr, expr_t&, date_interval_t, bool, bool");
+ }
+ virtual ~interval_posts() throw() {
+ TRACE_DTOR(interval_posts);
+ }
+
+ void report_subtotal(const date_interval_t& interval);
+
+ virtual void flush() {
+ if (last_post && interval.duration) {
+ if (interval.is_valid())
+ report_subtotal(interval);
+ subtotal_posts::flush();
+ }
+ }
+ virtual void operator()(post_t& post);
+};
+
+class posts_as_equity : public subtotal_posts
+{
+ post_t * last_post;
+ account_t& equity_account;
+ account_t * balance_account;
+
+ posts_as_equity();
+
+public:
+ posts_as_equity(post_handler_ptr _handler, expr_t& amount_expr)
+ : subtotal_posts(_handler, amount_expr),
+ equity_account(temps.create_account(_("Equity"))) {
+ TRACE_CTOR(posts_as_equity, "post_handler_ptr, expr_t&");
+ balance_account = equity_account.find_account(_("Opening Balances"));
+ }
+ virtual ~posts_as_equity() throw() {
+ TRACE_DTOR(posts_as_equity);
+ }
+
+ void report_subtotal();
+
+ virtual void flush() {
+ report_subtotal();
+ subtotal_posts::flush();
+ }
+};
+
+class by_payee_posts : public item_handler<post_t>
+{
+ typedef std::map<string, shared_ptr<subtotal_posts> > payee_subtotals_map;
+ typedef std::pair<string, shared_ptr<subtotal_posts> > payee_subtotals_pair;
+
+ expr_t& amount_expr;
+ payee_subtotals_map payee_subtotals;
+
+ by_payee_posts();
+
+ public:
+ by_payee_posts(post_handler_ptr handler, expr_t& _amount_expr)
+ : item_handler<post_t>(handler), amount_expr(_amount_expr) {
+ TRACE_CTOR(by_payee_posts, "post_handler_ptr, expr_t&");
+ }
+ virtual ~by_payee_posts() {
+ TRACE_DTOR(by_payee_posts);
+ }
+
+ virtual void flush();
+ virtual void operator()(post_t& post);
+};
+
+class transfer_details : public item_handler<post_t>
+{
+ account_t * master;
+ expr_t expr;
+ scope_t& scope;
+ temporaries_t temps;
+
+ transfer_details();
+
+public:
+ enum element_t {
+ SET_DATE,
+ SET_ACCOUNT,
+ SET_PAYEE
+ } which_element;
+
+ transfer_details(post_handler_ptr handler,
+ element_t _which_element,
+ account_t * _master,
+ const expr_t& _expr,
+ scope_t& _scope)
+ : item_handler<post_t>(handler), master(_master),
+ expr(_expr), scope(_scope), which_element(_which_element) {
+ TRACE_CTOR(transfer_details,
+ "post_handler_ptr, element_t, account_t *, expr_t, scope_t&");
+ }
+ virtual ~transfer_details() {
+ TRACE_DTOR(transfer_details);
+ }
+
+ virtual void operator()(post_t& post);
+};
+
+class dow_posts : public subtotal_posts
+{
+ posts_list days_of_the_week[7];
+
+ dow_posts();
+
+public:
+ dow_posts(post_handler_ptr handler, expr_t& amount_expr)
+ : subtotal_posts(handler, amount_expr) {
+ TRACE_CTOR(dow_posts, "post_handler_ptr, bool");
+ }
+ virtual ~dow_posts() throw() {
+ TRACE_DTOR(dow_posts);
+ }
+
+ virtual void flush();
+ virtual void operator()(post_t& post) {
+ days_of_the_week[post.date().day_of_week()].push_back(&post);
+ }
+};
+
+class generate_posts : public item_handler<post_t>
+{
+ generate_posts();
+
+protected:
+ typedef std::pair<date_interval_t, post_t *> pending_posts_pair;
+ typedef std::list<pending_posts_pair> pending_posts_list;
+
+ pending_posts_list pending_posts;
+ temporaries_t temps;
+
+public:
+ generate_posts(post_handler_ptr handler)
+ : item_handler<post_t>(handler) {
+ TRACE_CTOR(generate_posts, "post_handler_ptr");
+ }
+
+ virtual ~generate_posts() {
+ TRACE_DTOR(generate_posts);
+ }
+
+ void add_period_xacts(period_xacts_list& period_xacts);
+
+ virtual void add_post(const date_interval_t& period, post_t& post);
+};
+
+class budget_posts : public generate_posts
+{
+#define BUDGET_NO_BUDGET 0x00
+#define BUDGET_BUDGETED 0x01
+#define BUDGET_UNBUDGETED 0x02
+#define BUDGET_WRAP_VALUES 0x04
+
+ uint_least8_t flags;
+
+ budget_posts();
+
+public:
+ budget_posts(post_handler_ptr handler,
+ uint_least8_t _flags = BUDGET_BUDGETED)
+ : generate_posts(handler), flags(_flags) {
+ TRACE_CTOR(budget_posts, "post_handler_ptr, uint_least8_t");
+ }
+ virtual ~budget_posts() throw() {
+ TRACE_DTOR(budget_posts);
+ }
+
+ void report_budget_items(const date_t& date);
+
+ virtual void operator()(post_t& post);
+};
+
+class forecast_posts : public generate_posts
+{
+ predicate_t pred;
+ scope_t& context;
+ const std::size_t forecast_years;
+
+ public:
+ forecast_posts(post_handler_ptr handler,
+ const predicate_t& predicate,
+ scope_t& _context,
+ const std::size_t _forecast_years)
+ : generate_posts(handler), pred(predicate), context(_context),
+ forecast_years(_forecast_years) {
+ TRACE_CTOR(forecast_posts,
+ "post_handler_ptr, predicate_t, scope_t&, std::size_t");
+ }
+ virtual ~forecast_posts() throw() {
+ TRACE_DTOR(forecast_posts);
+ }
+
+ virtual void add_post(const date_interval_t& period, post_t& post);
+ virtual void flush();
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Account filters
+//
+
+class accounts_iterator;
+
+class pass_down_accounts : public item_handler<account_t>
+{
+ pass_down_accounts();
+
+ optional<predicate_t> pred;
+ optional<scope_t&> context;
+
+public:
+ pass_down_accounts(acct_handler_ptr handler,
+ accounts_iterator& iter,
+ const optional<predicate_t>& _pred = none,
+ const optional<scope_t&>& _context = none);
+
+ virtual ~pass_down_accounts() {
+ TRACE_DTOR(pass_down_accounts);
+ }
+};
+
+} // namespace ledger
+
+#endif // _FILTERS_H
diff --git a/src/flags.h b/src/flags.h
new file mode 100644
index 00000000..69e40e4b
--- /dev/null
+++ b/src/flags.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup util
+ */
+
+/**
+ * @file flags.h
+ * @author John Wiegley
+ *
+ * @ingroup util
+ */
+#ifndef _FLAGS_H
+#define _FLAGS_H
+
+
+template <typename T = boost::uint_least8_t, typename U = T>
+class supports_flags
+{
+public:
+ typedef T flags_t;
+
+protected:
+ flags_t _flags;
+
+public:
+ supports_flags() : _flags(static_cast<T>(0)) {
+ TRACE_CTOR(supports_flags, "");
+ }
+ supports_flags(const supports_flags& arg) : _flags(arg._flags) {
+ TRACE_CTOR(supports_flags, "copy");
+ }
+ supports_flags(const flags_t& arg) : _flags(arg) {
+ TRACE_CTOR(supports_flags, "const flags_t&");
+ }
+ ~supports_flags() throw() {
+ TRACE_DTOR(supports_flags);
+ }
+
+ supports_flags& operator=(const supports_flags& other) {
+ _flags = other._flags;
+ return *this;
+ }
+
+ flags_t flags() const {
+ return _flags;
+ }
+ bool has_flags(const flags_t arg) const {
+ return _flags & arg;
+ }
+
+ void set_flags(const flags_t arg) {
+ _flags = arg;
+ }
+ void clear_flags() {
+ _flags = static_cast<T>(0);
+ }
+ void add_flags(const flags_t arg) {
+ _flags = static_cast<T>(static_cast<U>(_flags) | static_cast<U>(arg));
+ }
+ void drop_flags(const flags_t arg) {
+ _flags = static_cast<T>(static_cast<U>(_flags) & static_cast<U>(~arg));
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */)
+ {
+ ar & _flags;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+template <typename T = boost::uint_least8_t, typename U = T>
+class basic_flags_t : public supports_flags<T, U>
+{
+public:
+ basic_flags_t() {
+ TRACE_CTOR(basic_flags_t, "");
+ }
+ basic_flags_t(const T& bits) {
+ TRACE_CTOR(basic_flags_t, "const T&");
+ set_flags(bits);
+ }
+ basic_flags_t(const U& bits) {
+ TRACE_CTOR(basic_flags_t, "const U&");
+ set_flags(static_cast<T>(bits));
+ }
+ ~basic_flags_t() throw() {
+ TRACE_DTOR(basic_flags_t);
+ }
+
+ basic_flags_t(const basic_flags_t& other)
+ : supports_flags<T, U>(other) {
+ TRACE_CTOR(basic_flags_t, "copy");
+ }
+ basic_flags_t& operator=(const basic_flags_t& other) {
+ set_flags(other.flags());
+ return *this;
+ }
+ basic_flags_t& operator=(const T& bits) {
+ set_flags(bits);
+ return *this;
+ }
+
+ operator T() const {
+ return supports_flags<T, U>::flags();
+ }
+ operator U() const {
+ return supports_flags<T, U>::flags();
+ }
+
+ basic_flags_t plus_flags(const T& arg) const {
+ basic_flags_t temp(*this);
+ temp.add_flags(arg);
+ return temp;
+ }
+ basic_flags_t minus_flags(const T& arg) const {
+ basic_flags_t temp(*this);
+ temp.drop_flags(arg);
+ return temp;
+ }
+};
+
+template <typename T = boost::uint_least8_t>
+class delegates_flags : public boost::noncopyable
+{
+public:
+ typedef T flags_t;
+
+protected:
+ supports_flags<T>& _flags;
+
+public:
+ delegates_flags() : _flags() {
+ TRACE_CTOR(delegates_flags, "");
+ }
+ delegates_flags(supports_flags<T>& arg) : _flags(arg) {
+ TRACE_CTOR(delegates_flags, "const supports_flags<T>&");
+ }
+ ~delegates_flags() throw() {
+ TRACE_DTOR(delegates_flags);
+ }
+
+ flags_t flags() const {
+ return _flags.flags();
+ }
+ bool has_flags(const flags_t arg) const {
+ return _flags.has_flags(arg);
+ }
+
+ void set_flags(const flags_t arg) {
+ _flags.set_flags(arg);
+ }
+ void clear_flags() {
+ _flags.clear_flags();
+ }
+ void add_flags(const flags_t arg) {
+ _flags.add_flags(arg);
+ }
+ void drop_flags(const flags_t arg) {
+ _flags.drop_flags(arg);
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */)
+ {
+ ar & _flags;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+#endif // _FLAGS_H
diff --git a/src/format.cc b/src/format.cc
new file mode 100644
index 00000000..f26a86a1
--- /dev/null
+++ b/src/format.cc
@@ -0,0 +1,488 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "format.h"
+#include "scope.h"
+#include "pstream.h"
+
+namespace ledger {
+
+format_t::elision_style_t format_t::default_style = TRUNCATE_TRAILING;
+bool format_t::default_style_changed = false;
+
+void format_t::element_t::dump(std::ostream& out) const
+{
+ out << "Element: ";
+
+ switch (type) {
+ case STRING: out << " STRING"; break;
+ case EXPR: out << " EXPR"; break;
+ }
+
+ out << " flags: 0x" << std::hex << int(flags());
+ out << " min: ";
+ out << std::right;
+ out.width(2);
+ out << std::dec << int(min_width);
+ out << " max: ";
+ out << std::right;
+ out.width(2);
+ out << std::dec << int(max_width);
+
+ switch (type) {
+ case STRING:
+ out << " str: '" << boost::get<string>(data) << "'" << std::endl;
+ break;
+ case EXPR:
+ out << " expr: " << boost::get<expr_t>(data) << std::endl;
+ break;
+ }
+}
+
+namespace {
+ expr_t parse_single_expression(const char *& p, bool single_expr = true)
+ {
+ string temp(p);
+ ptristream str(const_cast<char *&>(p));
+ expr_t expr;
+ expr.parse(str, single_expr ? PARSE_SINGLE : PARSE_PARTIAL, temp);
+ if (str.eof()) {
+ expr.set_text(p);
+ p += std::strlen(p);
+ } else {
+ assert(str.good());
+ istream_pos_type pos = str.tellg();
+ expr.set_text(string(p, p + long(pos)));
+ p += long(pos) - 1;
+
+ // Don't gobble up any whitespace
+ const char * base = p;
+ while (p >= base && std::isspace(*p))
+ p--;
+ }
+ return expr;
+ }
+}
+
+format_t::element_t * format_t::parse_elements(const string& fmt,
+ const optional<format_t&>& tmpl)
+{
+ std::auto_ptr<element_t> result;
+
+ element_t * current = NULL;
+
+ char buf[1024];
+ char * q = buf;
+
+ for (const char * p = fmt.c_str(); *p; p++) {
+ if (*p != '%' && *p != '\\') {
+ *q++ = *p;
+ continue;
+ }
+
+ if (! result.get()) {
+ result.reset(new element_t);
+ current = result.get();
+ } else {
+ current->next.reset(new element_t);
+ current = current->next.get();
+ }
+
+ if (q != buf) {
+ current->type = element_t::STRING;
+ current->data = string(buf, q);
+ q = buf;
+
+ current->next.reset(new element_t);
+ current = current->next.get();
+ }
+
+ if (*p == '\\') {
+ p++;
+ current->type = element_t::STRING;
+ switch (*p) {
+ case 'b': current->data = string("\b"); break;
+ case 'f': current->data = string("\f"); break;
+ case 'n': current->data = string("\n"); break;
+ case 'r': current->data = string("\r"); break;
+ case 't': current->data = string("\t"); break;
+ case 'v': current->data = string("\v"); break;
+ case '\\': current->data = string("\\"); break;
+ default: current->data = string(1, *p); break;
+ }
+ continue;
+ }
+
+ ++p;
+ while (*p == '-') {
+ switch (*p) {
+ case '-':
+ current->add_flags(ELEMENT_ALIGN_LEFT);
+ break;
+ }
+ ++p;
+ }
+
+ std::size_t num = 0;
+ while (*p && std::isdigit(*p)) {
+ num *= 10;
+ num += *p++ - '0';
+ }
+ current->min_width = num;
+
+ if (*p == '.') {
+ ++p;
+ num = 0;
+ while (*p && std::isdigit(*p)) {
+ num *= 10;
+ num += *p++ - '0';
+ }
+ current->max_width = num;
+ if (current->min_width == 0)
+ current->min_width = current->max_width;
+ }
+
+ switch (*p) {
+ case '%':
+ current->type = element_t::STRING;
+ current->data = string("%");
+ break;
+
+ case '$': {
+ if (! tmpl)
+ throw_(format_error, _("Prior field reference, but no template"));
+
+ p++;
+ if (*p == '0' || (! std::isdigit(*p) &&
+ *p != 'A' && *p != 'B' && *p != 'C' &&
+ *p != 'D' && *p != 'E' && *p != 'F'))
+ throw_(format_error, _("%$ field reference must be a digit from 1-9"));
+
+ unsigned int index = std::isdigit(*p) ? *p - '0' : (*p - 'A' + 10);
+ element_t * tmpl_elem = tmpl->elements.get();
+
+ for (unsigned int i = 1; i < index && tmpl_elem; i++) {
+ tmpl_elem = tmpl_elem->next.get();
+ while (tmpl_elem && tmpl_elem->type != element_t::EXPR)
+ tmpl_elem = tmpl_elem->next.get();
+ }
+
+ if (! tmpl_elem)
+ throw_(format_error, _("%$ reference to a non-existent prior field"));
+
+ *current = *tmpl_elem;
+ break;
+ }
+
+ case '(':
+ case '{': {
+ bool format_amount = *p == '{';
+ if (format_amount) p++;
+
+ current->type = element_t::EXPR;
+ current->data = parse_single_expression(p, ! format_amount);
+
+ // Wrap the subexpression in calls to justify and scrub
+ if (format_amount) {
+ if (! *p || *(p + 1) != '}')
+ throw_(format_error, _("Expected closing brace"));
+ else
+ p++;
+
+ expr_t::ptr_op_t op = boost::get<expr_t>(current->data).get_op();
+
+ expr_t::ptr_op_t amount_op;
+ expr_t::ptr_op_t colorize_op;
+ if (op->kind == expr_t::op_t::O_CONS) {
+ amount_op = op->left();
+ colorize_op = op->right();
+ } else {
+ amount_op = op;
+ }
+
+ expr_t::ptr_op_t scrub_node(new expr_t::op_t(expr_t::op_t::IDENT));
+ scrub_node->set_ident("scrub");
+
+ expr_t::ptr_op_t call1_node(new expr_t::op_t(expr_t::op_t::O_CALL));
+ call1_node->set_left(scrub_node);
+ call1_node->set_right(amount_op);
+
+ expr_t::ptr_op_t arg1_node(new expr_t::op_t(expr_t::op_t::VALUE));
+ expr_t::ptr_op_t arg2_node(new expr_t::op_t(expr_t::op_t::VALUE));
+ expr_t::ptr_op_t arg3_node(new expr_t::op_t(expr_t::op_t::VALUE));
+
+ arg1_node->set_value(current->min_width > 0 ?
+ long(current->min_width) : -1);
+ arg2_node->set_value(current->max_width > 0 ?
+ long(current->max_width) : -1);
+ arg3_node->set_value(! current->has_flags(ELEMENT_ALIGN_LEFT));
+
+ current->min_width = 0;
+ current->max_width = 0;
+
+ expr_t::ptr_op_t args1_node(new expr_t::op_t(expr_t::op_t::O_CONS));
+ args1_node->set_left(arg2_node);
+ args1_node->set_right(arg3_node);
+
+ expr_t::ptr_op_t args2_node(new expr_t::op_t(expr_t::op_t::O_CONS));
+ args2_node->set_left(arg1_node);
+ args2_node->set_right(args1_node);
+
+ expr_t::ptr_op_t args3_node(new expr_t::op_t(expr_t::op_t::O_CONS));
+ args3_node->set_left(call1_node);
+ args3_node->set_right(args2_node);
+
+ expr_t::ptr_op_t seq1_node(new expr_t::op_t(expr_t::op_t::O_SEQ));
+ seq1_node->set_left(args3_node);
+
+ expr_t::ptr_op_t justify_node(new expr_t::op_t(expr_t::op_t::IDENT));
+ justify_node->set_ident("justify");
+
+ expr_t::ptr_op_t call2_node(new expr_t::op_t(expr_t::op_t::O_CALL));
+ call2_node->set_left(justify_node);
+ call2_node->set_right(seq1_node);
+
+ string prev_expr = boost::get<expr_t>(current->data).text();
+
+ if (colorize_op) {
+ expr_t::ptr_op_t ansify_if_node(new expr_t::op_t(expr_t::op_t::IDENT));
+ ansify_if_node->set_ident("ansify_if");
+
+ expr_t::ptr_op_t args4_node(new expr_t::op_t(expr_t::op_t::O_CONS));
+ args4_node->set_left(call2_node);
+ args4_node->set_right(colorize_op);
+
+ expr_t::ptr_op_t seq2_node(new expr_t::op_t(expr_t::op_t::O_SEQ));
+ seq2_node->set_left(args4_node);
+
+ expr_t::ptr_op_t call3_node(new expr_t::op_t(expr_t::op_t::O_CALL));
+ call3_node->set_left(ansify_if_node);
+ call3_node->set_right(seq2_node);
+
+ current->data = expr_t(call3_node);
+ } else {
+ current->data = expr_t(call2_node);
+ }
+
+ boost::get<expr_t>(current->data).set_text(prev_expr);
+ }
+ break;
+ }
+
+ default:
+ throw_(format_error, _("Unrecognized formatting character: %1") << *p);
+ }
+ }
+
+ if (q != buf) {
+ if (! result.get()) {
+ result.reset(new element_t);
+ current = result.get();
+ } else {
+ current->next.reset(new element_t);
+ current = current->next.get();
+ }
+ current->type = element_t::STRING;
+ current->data = string(buf, q);
+ }
+
+ return result.release();
+}
+
+string format_t::real_calc(scope_t& scope)
+{
+ std::ostringstream out_str;
+
+ for (element_t * elem = elements.get(); elem; elem = elem->next.get()) {
+ std::ostringstream out;
+ string name;
+
+ if (elem->has_flags(ELEMENT_ALIGN_LEFT))
+ out << std::left;
+ else
+ out << std::right;
+
+ switch (elem->type) {
+ case element_t::STRING:
+ if (elem->min_width > 0)
+ out.width(elem->min_width);
+ out << boost::get<string>(elem->data);
+ break;
+
+ case element_t::EXPR: {
+ expr_t& expr(boost::get<expr_t>(elem->data));
+ try {
+
+ expr.compile(scope);
+
+ value_t value;
+ if (expr.is_function()) {
+ call_scope_t args(scope);
+ args.push_back(long(elem->max_width));
+ value = expr.get_function()(args);
+ } else {
+ value = expr.calc(scope);
+ }
+ DEBUG("format.expr", "value = (" << value << ")");
+
+ if (elem->min_width > 0)
+ value.print(out, static_cast<int>(elem->min_width), -1,
+ ! elem->has_flags(ELEMENT_ALIGN_LEFT));
+ else
+ out << value.to_string();
+ }
+ catch (const calc_error&) {
+ add_error_context(_("While calculating format expression:"));
+ add_error_context(expr.context_to_str());
+ throw;
+ }
+ break;
+ }
+
+ default:
+ assert(false);
+ break;
+ }
+
+ if (elem->max_width > 0 || elem->min_width > 0) {
+ unistring temp(out.str());
+ string result;
+
+ if (elem->max_width > 0 && elem->max_width < temp.length()) {
+ result = truncate(temp, elem->max_width);
+ } else {
+ result = temp.extract();
+ if (elem->min_width > temp.length())
+ for (std::size_t i = 0; i < elem->min_width - temp.length(); i++)
+ result += " ";
+ }
+ out_str << result;
+ } else {
+ out_str << out.str();
+ }
+ }
+
+ return out_str.str();
+}
+
+string format_t::truncate(const unistring& ustr,
+ const std::size_t width,
+ const std::size_t account_abbrev_length)
+{
+ assert(width < 4095);
+
+ const std::size_t len = ustr.length();
+ if (width == 0 || len <= width)
+ return ustr.extract();
+
+ std::ostringstream buf;
+
+ elision_style_t style = default_style;
+ if (account_abbrev_length > 0 && ! default_style_changed)
+ style = ABBREVIATE;
+
+ switch (style) {
+ case TRUNCATE_LEADING:
+ // This method truncates at the beginning.
+ buf << ".." << ustr.extract(len - (width - 2), width - 2);
+ break;
+
+ case TRUNCATE_MIDDLE:
+ // This method truncates in the middle.
+ buf << ustr.extract(0, (width - 2) / 2)
+ << ".."
+ << ustr.extract(len - ((width - 2) / 2 + (width - 2) % 2),
+ (width - 2) / 2 + (width - 2) % 2);
+ break;
+
+ case ABBREVIATE:
+ if (account_abbrev_length > 0) {
+ std::list<string> parts;
+ string::size_type beg = 0;
+ string strcopy(ustr.extract());
+ for (string::size_type pos = strcopy.find(':');
+ pos != string::npos;
+ beg = pos + 1, pos = strcopy.find(':', beg))
+ parts.push_back(string(strcopy, beg, pos - beg));
+ parts.push_back(string(strcopy, beg));
+
+ std::ostringstream result;
+
+ std::size_t newlen = len;
+ for (std::list<string>::iterator i = parts.begin();
+ i != parts.end();
+ i++) {
+ // Don't contract the last element
+ std::list<string>::iterator x = i;
+ if (++x == parts.end()) {
+ result << *i;
+ break;
+ }
+
+ if (newlen > width) {
+ unistring temp(*i);
+ if (temp.length() > account_abbrev_length) {
+ result << temp.extract(0, account_abbrev_length) << ":";
+ newlen -= temp.length() - account_abbrev_length;
+ } else {
+ result << temp.extract() << ":";
+ newlen -= temp.length();
+ }
+ } else {
+ result << *i << ":";
+ }
+ }
+
+ if (newlen > width) {
+ // Even abbreviated its too big to show the last account, so
+ // abbreviate all but the last and truncate at the beginning.
+ unistring temp(result.str());
+ assert(temp.length() > width - 2);
+ buf << ".." << temp.extract(temp.length() - (width - 2), width - 2);
+ } else {
+ buf << result.str();
+ }
+ break;
+ }
+ // fall through...
+
+ case TRUNCATE_TRAILING:
+ // This method truncates at the end (the default).
+ buf << ustr.extract(0, width - 2) << "..";
+ break;
+ }
+
+ return buf.str();
+}
+
+} // namespace ledger
diff --git a/src/format.h b/src/format.h
new file mode 100644
index 00000000..a2bf1015
--- /dev/null
+++ b/src/format.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup expr
+ */
+
+/**
+ * @file format.h
+ * @author John Wiegley
+ *
+ * @ingroup expr
+ */
+#ifndef _FORMAT_H
+#define _FORMAT_H
+
+#include "expr.h"
+#include "unistring.h"
+
+namespace ledger {
+
+class unistring;
+
+DECLARE_EXCEPTION(format_error, std::runtime_error);
+
+class format_t : public expr_base_t<string>
+{
+ typedef expr_base_t<string> base_type;
+
+ struct element_t : public supports_flags<>
+ {
+#define ELEMENT_ALIGN_LEFT 0x01
+
+ enum kind_t { STRING, EXPR };
+
+ kind_t type;
+ std::size_t min_width;
+ std::size_t max_width;
+ variant<string, expr_t> data;
+ scoped_ptr<struct element_t> next;
+
+ element_t() throw()
+ : supports_flags<>(), type(STRING), min_width(0), max_width(0) {
+ TRACE_CTOR(element_t, "");
+ }
+ ~element_t() throw() {
+ TRACE_DTOR(element_t);
+ }
+ element_t(const element_t& elem) : supports_flags<>() {
+ *this = elem;
+ }
+
+ element_t& operator=(const element_t& elem) {
+ if (this != &elem) {
+ supports_flags<>::operator=(elem);
+ type = elem.type;
+ min_width = elem.min_width;
+ max_width = elem.max_width;
+ data = elem.data;
+ }
+ return *this;
+ }
+
+ friend inline void mark_red(std::ostream& out, const element_t * elem) {
+ out.setf(std::ios::left);
+ out.width(0);
+ out << "\033[31m";
+
+ if (elem->has_flags(ELEMENT_ALIGN_LEFT))
+ out << std::left;
+ else
+ out << std::right;
+
+ if (elem->min_width > 0)
+ out.width(elem->min_width);
+ }
+
+ void dump(std::ostream& out) const;
+ };
+
+ scoped_ptr<element_t> elements;
+
+public:
+ static enum elision_style_t {
+ TRUNCATE_TRAILING,
+ TRUNCATE_MIDDLE,
+ TRUNCATE_LEADING,
+ ABBREVIATE
+ } default_style;
+
+ static bool default_style_changed;
+
+private:
+ static element_t * parse_elements(const string& fmt,
+ const optional<format_t&>& tmpl);
+
+public:
+ format_t() : base_type() {
+ TRACE_CTOR(format_t, "");
+ }
+ format_t(const string& _str, scope_t * context = NULL)
+ : base_type(context) {
+ TRACE_CTOR(format_t, "const string&");
+ if (! _str.empty())
+ parse_format(_str);
+ }
+ virtual ~format_t() {
+ TRACE_DTOR(format_t);
+ }
+
+ void parse_format(const string& _format,
+ const optional<format_t&>& tmpl = none) {
+ elements.reset(parse_elements(_format, tmpl));
+ set_text(_format);
+ }
+
+ virtual result_type real_calc(scope_t& scope);
+
+ virtual void dump(std::ostream& out) const {
+ for (const element_t * elem = elements.get();
+ elem;
+ elem = elem->next.get())
+ elem->dump(out);
+ }
+
+ static string truncate(const unistring& str,
+ const std::size_t width,
+ const std::size_t account_abbrev_length = 0);
+};
+
+} // namespace ledger
+
+#endif // _FORMAT_H
diff --git a/src/generate.cc b/src/generate.cc
new file mode 100644
index 00000000..3549adc8
--- /dev/null
+++ b/src/generate.cc
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "generate.h"
+#include "session.h"
+
+namespace ledger {
+
+generate_posts_iterator::generate_posts_iterator
+ (session_t& _session,
+ unsigned int _seed,
+ std::size_t _quantity,
+ bool _allow_invalid)
+ : session(_session), seed(_seed), quantity(_quantity),
+ allow_invalid(_allow_invalid),
+
+ rnd_gen(seed == 0 ? static_cast<unsigned int>(std::time(0)) : seed),
+
+ year_range(1900, 2300), year_gen(rnd_gen, year_range),
+ mon_range(1, 12), mon_gen(rnd_gen, mon_range),
+ day_range(1, 28), day_gen(rnd_gen, day_range),
+
+ upchar_range('A', 'Z'), upchar_gen(rnd_gen, upchar_range),
+ downchar_range('a', 'z'), downchar_gen(rnd_gen, downchar_range),
+ numchar_range('0', '9'), numchar_gen(rnd_gen, numchar_range),
+
+ truth_range(0, 1), truth_gen(rnd_gen, truth_range),
+ three_range(1, 3), three_gen(rnd_gen, three_range),
+ six_range(1, 6), six_gen(rnd_gen, six_range),
+ two_six_range(2, 6), two_six_gen(rnd_gen, two_six_range),
+ strlen_range(1, 40), strlen_gen(rnd_gen, strlen_range),
+
+ neg_number_range(-1000000, -1), neg_number_gen(rnd_gen, neg_number_range),
+ pos_number_range(1, 1000000), pos_number_gen(rnd_gen, pos_number_range)
+{
+ TRACE_CTOR(generate_posts_iterator, "bool");
+
+ std::ostringstream next_date_buf;
+ generate_date(next_date_buf);
+ next_date = parse_date(next_date_buf.str());
+
+ std::ostringstream next_eff_date_buf;
+ generate_date(next_eff_date_buf);
+ next_eff_date = parse_date(next_eff_date_buf.str());
+
+}
+
+void generate_posts_iterator::generate_string(std::ostream& out, int len,
+ bool only_alpha)
+{
+ DEBUG("generate.post.string",
+ "Generating string of length " << len << ", only alpha " << only_alpha);
+
+ int last = -1;
+ bool first = true;
+ for (int i = 0; i < len; i++) {
+ int next = only_alpha ? 3 : three_gen();
+ bool output = true;
+ switch (next) {
+ case 1: // colon
+ if (! first && last == 3 && strlen_gen() % 10 == 0 && i + 1 != len)
+ out << ':';
+ else {
+ i--;
+ output = false;
+ }
+ break;
+ case 2: // space
+ if (! first && last == 3 && strlen_gen() % 20 == 0 && i + 1 != len)
+ out << ' ';
+ else {
+ i--;
+ output = false;
+ }
+ break;
+ case 3: // character
+ switch (three_gen()) {
+ case 1: // uppercase
+ out << char(upchar_gen());
+ break;
+ case 2: // lowercase
+ out << char(downchar_gen());
+ break;
+ case 3: // number
+ if (! only_alpha && ! first)
+ out << char(numchar_gen());
+ else {
+ i--;
+ output = false;
+ }
+ break;
+ }
+ break;
+ }
+ if (output) {
+ last = next;
+ first = false;
+ }
+ }
+}
+
+bool generate_posts_iterator::generate_account(std::ostream& out,
+ bool no_virtual)
+{
+ bool must_balance = true;
+ bool is_virtual = false;
+
+ if (! no_virtual) {
+ switch (three_gen()) {
+ case 1:
+ out << '[';
+ is_virtual = true;
+ break;
+ case 2:
+ out << '(';
+ must_balance = false;
+ is_virtual = true;
+ break;
+ case 3:
+ break;
+ }
+ }
+
+ generate_string(out, strlen_gen());
+
+ if (is_virtual) {
+ if (must_balance)
+ out << ']';
+ else
+ out << ')';
+ }
+
+ return must_balance;
+}
+
+void generate_posts_iterator::generate_commodity(std::ostream& out)
+{
+ string comm;
+ do {
+ std::ostringstream buf;
+ generate_string(buf, six_gen(), true);
+ comm = buf.str();
+ }
+ while (comm == "h" || comm == "m" || comm == "s" ||
+ comm == "and" || comm == "div" || comm == "false" ||
+ comm == "or" || comm == "not" || comm == "true" ||
+ comm == "if" || comm == "else");
+
+ out << comm;
+}
+
+string generate_posts_iterator::generate_amount(std::ostream& out,
+ value_t not_this_amount,
+ bool no_negative)
+{
+ std::ostringstream buf;
+
+ if (truth_gen()) { // commodity goes in front
+ generate_commodity(buf);
+ if (truth_gen())
+ buf << ' ';
+ if (no_negative || truth_gen())
+ buf << pos_number_gen();
+ else
+ buf << neg_number_gen();
+ } else {
+ if (no_negative || truth_gen())
+ buf << pos_number_gen();
+ else
+ buf << neg_number_gen();
+ if (truth_gen())
+ buf << ' ';
+ generate_commodity(buf);
+ }
+
+ // Possibly generate an annotized commodity, but make it rarer
+ if (! no_negative && three_gen() == 1) {
+ if (three_gen() == 1) {
+ buf << " {";
+ generate_amount(buf, value_t(), true);
+ buf << '}';
+ }
+ if (six_gen() == 1) {
+ buf << " [";
+ generate_date(buf);
+ buf << ']';
+ }
+ if (six_gen() == 1) {
+ buf << " (";
+ generate_string(buf, six_gen());
+ buf << ')';
+ }
+ }
+
+ if (! not_this_amount.is_null() &&
+ value_t(buf.str()).as_amount().commodity() ==
+ not_this_amount.as_amount().commodity())
+ return "";
+
+ out << buf.str();
+
+ return buf.str();
+}
+
+bool generate_posts_iterator::generate_post(std::ostream& out, bool no_amount)
+{
+ out << " ";
+ bool must_balance = generate_account(out, no_amount);
+ out << " ";
+
+ if (! no_amount) {
+ value_t amount(generate_amount(out));
+ if (truth_gen())
+ generate_cost(out, amount);
+ }
+ if (truth_gen())
+ generate_note(out);
+ out << '\n';
+
+ return must_balance;
+}
+
+void generate_posts_iterator::generate_cost(std::ostream& out, value_t amount)
+{
+ std::ostringstream buf;
+
+ if (truth_gen())
+ buf << " @ ";
+ else
+ buf << " @@ ";
+
+ if (! generate_amount(buf, amount, true).empty())
+ out << buf.str();
+}
+
+void generate_posts_iterator::generate_date(std::ostream& out)
+{
+ out.width(4);
+ out.fill('0');
+ out << year_gen();
+
+ out.width(1);
+ out << '/';
+
+ out.width(2);
+ out.fill('0');
+ out << mon_gen();
+
+ out.width(1);
+ out << '/';
+
+ out.width(2);
+ out.fill('0');
+ out << day_gen();
+}
+
+void generate_posts_iterator::generate_state(std::ostream& out)
+{
+ switch (three_gen()) {
+ case 1:
+ out << "* ";
+ break;
+ case 2:
+ out << "! ";
+ break;
+ case 3:
+ out << "";
+ break;
+ }
+}
+
+void generate_posts_iterator::generate_code(std::ostream& out)
+{
+ out << '(';
+ generate_string(out, six_gen());
+ out << ") ";
+}
+
+void generate_posts_iterator::generate_payee(std::ostream& out)
+{
+ generate_string(out, strlen_gen());
+}
+
+void generate_posts_iterator::generate_note(std::ostream& out)
+{
+ out << "\n ; ";
+ generate_string(out, strlen_gen());
+}
+
+void generate_posts_iterator::generate_xact(std::ostream& out)
+{
+ out << format_date(next_date, FMT_WRITTEN);
+ next_date += gregorian::days(six_gen());
+ if (truth_gen()) {
+ out << '=';
+ out << format_date(next_eff_date, FMT_WRITTEN);
+ next_eff_date += gregorian::days(six_gen());
+ }
+ out << ' ';
+
+ generate_state(out);
+ generate_code(out);
+ generate_payee(out);
+ if (truth_gen())
+ generate_note(out);
+ out << '\n';
+
+ int count = three_gen() * 2;
+ bool has_must_balance = false;
+ for (int i = 0; i < count; i++) {
+ if (generate_post(out))
+ has_must_balance = true;
+ }
+ if (has_must_balance)
+ generate_post(out, true);
+
+ out << '\n';
+}
+
+post_t * generate_posts_iterator::operator()()
+{
+ post_t * post = posts();
+ if (post == NULL && quantity > 0) {
+ std::ostringstream buf;
+ generate_xact(buf);
+
+ DEBUG("generate.post", "The post we intend to parse:\n" << buf.str());
+
+ std::istringstream in(buf.str());
+ try {
+ if (session.journal->parse(in, session) != 0) {
+ VERIFY(session.journal->xacts.back()->valid());
+ posts.reset(*session.journal->xacts.back());
+ post = posts();
+ }
+ }
+ catch (std::exception& err) {
+ add_error_context(_("While parsing generated transaction (seed %1):")
+ << seed);
+ add_error_context(buf.str());
+ throw;
+ }
+ catch (int status) {
+ add_error_context(_("While parsing generated transaction (seed %1):")
+ << seed);
+ add_error_context(buf.str());
+ throw;
+ }
+
+ quantity--;
+ }
+ return post;
+}
+
+} // namespace ledger
diff --git a/src/generate.h b/src/generate.h
new file mode 100644
index 00000000..66513fc8
--- /dev/null
+++ b/src/generate.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup generate
+ */
+
+/**
+ * @file generate.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _GENERATE_H
+#define _GENERATE_H
+
+#include "iterators.h"
+
+namespace ledger {
+
+class session_t;
+
+class generate_posts_iterator : public posts_iterator
+{
+ session_t& session;
+ unsigned int seed;
+ std::size_t quantity;
+ bool allow_invalid;
+ date_t next_date;
+ date_t next_eff_date;
+
+ mt19937 rnd_gen;
+
+ typedef variate_generator<mt19937&, uniform_int<> > int_generator_t;
+ typedef variate_generator<mt19937&, uniform_real<> > real_generator_t;
+
+ uniform_int<> year_range;
+ int_generator_t year_gen;
+ uniform_int<> mon_range;
+ int_generator_t mon_gen;
+ uniform_int<> day_range;
+ int_generator_t day_gen;
+
+ uniform_int<> upchar_range;
+ int_generator_t upchar_gen;
+ uniform_int<> downchar_range;
+ int_generator_t downchar_gen;
+ uniform_int<> numchar_range;
+ int_generator_t numchar_gen;
+
+ uniform_int<> truth_range;
+ int_generator_t truth_gen;
+ uniform_int<> three_range;
+ int_generator_t three_gen;
+ uniform_int<> six_range;
+ int_generator_t six_gen;
+ uniform_int<> two_six_range;
+ int_generator_t two_six_gen;
+
+ uniform_int<> strlen_range;
+ int_generator_t strlen_gen;
+
+ uniform_real<> neg_number_range;
+ real_generator_t neg_number_gen;
+ uniform_real<> pos_number_range;
+ real_generator_t pos_number_gen;
+
+ xact_posts_iterator posts;
+
+public:
+ generate_posts_iterator(session_t& _session,
+ unsigned int _seed = 0,
+ std::size_t _quantity = 100,
+ bool _allow_invalid = false);
+
+ virtual ~generate_posts_iterator() throw() {
+ TRACE_DTOR(generate_posts_iterator);
+ }
+
+ virtual post_t * operator()();
+
+protected:
+ void generate_string(std::ostream& out, int len, bool only_alpha = false);
+ bool generate_account(std::ostream& out, bool no_virtual = false);
+ void generate_commodity(std::ostream& out);
+ string generate_amount(std::ostream& out,
+ value_t not_this_amount = NULL_VALUE,
+ bool no_negative = false);
+ bool generate_post(std::ostream& out, bool no_amount = false);
+ void generate_cost(std::ostream& out, value_t amount);
+ void generate_date(std::ostream& out);
+ void generate_state(std::ostream& out);
+ void generate_code(std::ostream& out);
+ void generate_payee(std::ostream& out);
+ void generate_note(std::ostream& out);
+ void generate_xact(std::ostream& out);
+};
+
+} // namespace ledger
+
+#endif // _GENERATE_H
diff --git a/src/global.cc b/src/global.cc
new file mode 100644
index 00000000..e120e5d5
--- /dev/null
+++ b/src/global.cc
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "global.h"
+#if defined(HAVE_BOOST_PYTHON)
+#include "pyinterp.h"
+#else
+#include "session.h"
+#endif
+#include "item.h"
+#include "journal.h"
+#include "pool.h"
+
+namespace ledger {
+
+static bool args_only = false;
+
+global_scope_t::global_scope_t(char ** envp)
+{
+ TRACE_CTOR(global_scope_t, "");
+
+#if defined(HAVE_BOOST_PYTHON)
+ if (! python_session.get()) {
+ python_session.reset(new ledger::python_interpreter_t);
+ session_ptr = python_session;
+ }
+#else
+ session_ptr.reset(new session_t);
+#endif
+
+ set_session_context(session_ptr.get());
+
+ // Create the report object, which maintains state relating to each
+ // command invocation. Because we're running from main(), the
+ // distinction between session and report doesn't really matter, but if
+ // a GUI were calling into Ledger it would have one session object per
+ // open document, with a separate report_t object for each report it
+ // generated.
+ report_stack.push_front(new report_t(session()));
+ scope_t::default_scope = &report();
+
+ // Read the user's options, in the following order:
+ //
+ // 1. environment variables (LEDGER_<option>)
+ // 2. initialization file (~/.ledgerrc)
+ // 3. command-line (--option or -o)
+ //
+ // Before processing command-line options, we must notify the session object
+ // that such options are beginning, since options like -f cause a complete
+ // override of files found anywhere else.
+ if (! args_only) {
+ session().set_flush_on_next_data_file(true);
+ read_environment_settings(envp);
+ session().set_flush_on_next_data_file(true);
+ read_init();
+ } else {
+ session().HANDLER(price_db_).off();
+ }
+}
+
+global_scope_t::~global_scope_t()
+{
+ TRACE_DTOR(global_scope_t);
+
+ // If memory verification is being performed (which can be very slow),
+ // clean up everything by closing the session and deleting the session
+ // object, and then shutting down the memory tracing subsystem.
+ // Otherwise, let it all leak because we're about to exit anyway.
+ IF_VERIFY() set_session_context(NULL);
+
+#if defined(HAVE_BOOST_PYTHON)
+ python_session.reset();
+#endif
+}
+
+void global_scope_t::read_init()
+{
+ if (HANDLED(init_file_)) {
+ path init_file(HANDLER(init_file_).str());
+ if (exists(init_file)) {
+ TRACE_START(init, 1, "Read initialization file");
+
+ ifstream init(init_file);
+
+ if (session().journal->read(init_file, NULL, &report()) > 0 ||
+ session().journal->auto_xacts.size() > 0 ||
+ session().journal->period_xacts.size() > 0) {
+ throw_(parse_error, _("Transactions found in initialization file '%1'")
+ << init_file);
+ }
+
+ TRACE_FINISH(init, 1);
+ }
+ }
+}
+
+char * global_scope_t::prompt_string()
+{
+ static char prompt[32];
+ std::size_t i;
+ for (i = 0; i < report_stack.size(); i++)
+ prompt[i] = ']';
+ prompt[i++] = ' ';
+ prompt[i] = '\0';
+ return prompt;
+}
+
+void global_scope_t::report_error(const std::exception& err)
+{
+ std::cout.flush(); // first display anything that was pending
+
+ if (caught_signal == NONE_CAUGHT) {
+ // Display any pending error context information
+ string context = error_context();
+ if (! context.empty())
+ std::cerr << context << std::endl;
+
+ std::cerr << _("Error: ") << err.what() << std::endl;
+ } else {
+ caught_signal = NONE_CAUGHT;
+ }
+}
+
+void global_scope_t::execute_command(strings_list args, bool at_repl)
+{
+ session().set_flush_on_next_data_file(true);
+
+ // Process the command verb, arguments and options
+ if (at_repl) {
+ args = read_command_arguments(report(), args);
+ if (args.empty())
+ return;
+ }
+
+ strings_list::iterator arg = args.begin();
+ string verb = *arg++;
+
+ // Look for a precommand first, which is defined as any defined function
+ // whose name starts with "ledger_precmd_". The difference between a
+ // precommand and a regular command is that precommands ignore the journal
+ // data file completely, nor is the user's init file read.
+ //
+ // Here are some examples of pre-commands:
+ //
+ // parse STRING ; show how a value expression is parsed
+ // eval STRING ; simply evaluate a value expression
+ // format STRING ; show how a format string is parsed
+ //
+ // If such a command is found, create the output stream for the result and
+ // then invoke the command.
+
+ expr_t::func_t command;
+ bool is_precommand = false;
+ bind_scope_t bound_scope(*this, report());
+
+ if (bool(command = look_for_precommand(bound_scope, verb)))
+ is_precommand = true;
+
+ // If it is not a pre-command, then parse the user's ledger data at this
+ // time if not done alreday (i.e., if not at a REPL). Then patch up the
+ // report options based on the command verb.
+
+ if (! is_precommand) {
+ if (! at_repl)
+ session().read_journal_files();
+
+ report().normalize_options(verb);
+
+ if (! bool(command = look_for_command(bound_scope, verb)))
+ throw_(std::logic_error, _("Unrecognized command '%1'") << verb);
+ }
+
+ // Create the output stream (it might be a file, the console or a PAGER
+ // subprocess) and invoke the report command. The output stream is closed
+ // by the caller of this function.
+
+ report().output_stream
+ .initialize(report().HANDLED(output_) ?
+ optional<path>(path(report().HANDLER(output_).str())) :
+ optional<path>(),
+ report().HANDLED(pager_) ?
+ optional<path>(path(report().HANDLER(pager_).str())) :
+ optional<path>());
+
+ // Now that the output stream is initialized, report the options that will
+ // participate in this report, if the user specified --options
+
+ if (HANDLED(options))
+ report_options(report(), report().output_stream);
+
+ // Create an argument scope containing the report command's arguments, and
+ // then invoke the command. The bound scope causes lookups to happen
+ // first in the global scope, and then in the report scope.
+
+ call_scope_t command_args(bound_scope);
+ for (strings_list::iterator i = arg; i != args.end(); i++)
+ command_args.push_back(string_value(*i));
+
+ INFO_START(command, "Finished executing command");
+ command(command_args);
+ INFO_FINISH(command);
+}
+
+int global_scope_t::execute_command_wrapper(strings_list args, bool at_repl)
+{
+ int status = 1;
+
+ try {
+ if (at_repl) push_report();
+ execute_command(args, at_repl);
+ if (at_repl) pop_report();
+
+ // If we've reached this point, everything succeeded fine. Ledger uses
+ // exceptions to notify of error conditions, so if you're using gdb,
+ // just type "catch throw" to find the source point of any error.
+ status = 0;
+ }
+ catch (const std::exception& err) {
+ if (at_repl) pop_report();
+ report_error(err);
+ }
+
+ return status;
+}
+
+void global_scope_t::report_options(report_t& report, std::ostream& out)
+{
+ out << "==============================================================================="
+ << std::endl;
+ out << "[Global scope options]" << std::endl;
+
+ HANDLER(args_only).report(out);
+ HANDLER(debug_).report(out);
+ HANDLER(init_file_).report(out);
+ HANDLER(script_).report(out);
+ HANDLER(trace_).report(out);
+ HANDLER(verbose).report(out);
+ HANDLER(verify).report(out);
+
+ out << std::endl << "[Session scope options]" << std::endl;
+ report.session.report_options(out);
+
+ out << std::endl << "[Report scope options]" << std::endl;
+ report.report_options(out);
+ out << "==============================================================================="
+ << std::endl;
+}
+
+option_t<global_scope_t> * global_scope_t::lookup_option(const char * p)
+{
+ switch (*p) {
+ case 'a':
+ OPT(args_only);
+ break;
+ case 'd':
+ OPT(debug_);
+ break;
+ case 'f':
+ OPT(full_help);
+ break;
+ case 'h':
+ OPT_(help);
+ else OPT(help_calc);
+ else OPT(help_comm);
+ else OPT(help_disp);
+ break;
+ case 'i':
+ OPT(init_file_);
+ break;
+ case 'o':
+ OPT(options);
+ break;
+ case 's':
+ OPT(script_);
+ break;
+ case 't':
+ OPT(trace_);
+ break;
+ case 'v':
+ OPT_(verbose);
+ else OPT(verify);
+ else OPT(version);
+ break;
+ }
+ return NULL;
+}
+
+expr_t::ptr_op_t global_scope_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
+{
+ switch (kind) {
+ case symbol_t::FUNCTION:
+ if (option_t<global_scope_t> * handler = lookup_option(name.c_str()))
+ return MAKE_OPT_FUNCTOR(global_scope_t, handler);
+ break;
+
+ case symbol_t::OPTION:
+ if (option_t<global_scope_t> * handler = lookup_option(name.c_str()))
+ return MAKE_OPT_HANDLER(global_scope_t, handler);
+ break;
+
+ case symbol_t::PRECOMMAND: {
+ const char * p = name.c_str();
+ switch (*p) {
+ case 'p':
+ if (is_eq(p, "push"))
+ return MAKE_FUNCTOR(global_scope_t::push_command);
+ else if (is_eq(p, "pop"))
+ return MAKE_FUNCTOR(global_scope_t::pop_command);
+ break;
+ }
+ }
+ default:
+ break;
+ }
+
+ // If you're wondering how symbols from report() will be found, it's
+ // because of the bind_scope_t object in execute_command() below.
+ return NULL;
+}
+
+void global_scope_t::read_environment_settings(char * envp[])
+{
+ TRACE_START(environment, 1, "Processed environment variables");
+
+ process_environment(const_cast<const char **>(envp), "LEDGER_", report());
+
+#if 1
+ // These are here for backwards compatability, but are deprecated.
+
+ if (const char * p = std::getenv("LEDGER")) {
+ if (! std::getenv("LEDGER_FILE"))
+ process_option("environ", "file", report(), p, "LEDGER");
+ }
+ if (const char * p = std::getenv("LEDGER_INIT")) {
+ if (! std::getenv("LEDGER_INIT_FILE"))
+ process_option("environ", "init-file", report(), p, "LEDGER_INIT");
+ }
+ if (const char * p = std::getenv("PRICE_HIST")) {
+ if (! std::getenv("LEDGER_PRICEDB"))
+ process_option("environ", "price-db", report(), p, "PRICE_HIST");
+ }
+ if (const char * p = std::getenv("PRICE_EXP"))
+ process_option("environ", "price-exp", report(), p, "PRICE_EXP");
+#endif
+
+ TRACE_FINISH(environment, 1);
+}
+
+strings_list
+global_scope_t::read_command_arguments(scope_t& scope, strings_list args)
+{
+ TRACE_START(arguments, 1, "Processed command-line arguments");
+
+ strings_list remaining = process_arguments(args, scope);
+
+ TRACE_FINISH(arguments, 1);
+
+ return remaining;
+}
+
+void global_scope_t::normalize_session_options()
+{
+ INFO("Initialization file is " << HANDLER(init_file_).str());
+ INFO("Price database is " << session().HANDLER(price_db_).str());
+
+ foreach (const path& pathname, session().HANDLER(file_).data_files)
+ INFO("Journal file is " << pathname.string());
+}
+
+expr_t::func_t global_scope_t::look_for_precommand(scope_t& scope,
+ const string& verb)
+{
+ if (expr_t::ptr_op_t def = scope.lookup(symbol_t::PRECOMMAND, verb))
+ return def->as_function();
+ else
+ return expr_t::func_t();
+}
+
+expr_t::func_t global_scope_t::look_for_command(scope_t& scope,
+ const string& verb)
+{
+ if (expr_t::ptr_op_t def = scope.lookup(symbol_t::COMMAND, verb))
+ return def->as_function();
+ else
+ return expr_t::func_t();
+}
+
+void global_scope_t::visit_man_page() const
+{
+ int pid = fork();
+ if (pid < 0) {
+ throw std::logic_error(_("Failed to fork child process"));
+ }
+ else if (pid == 0) { // child
+ execlp("man", "man", "1", "ledger", NULL);
+
+ // We should never, ever reach here
+ perror("execlp: man");
+ exit(1);
+ }
+
+ int status = -1;
+ wait(&status);
+ exit(0); // parent
+}
+
+void handle_debug_options(int argc, char * argv[])
+{
+ for (int i = 1; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (std::strcmp(argv[i], "--args-only") == 0) {
+ args_only = true;
+ }
+ else if (std::strcmp(argv[i], "--verify") == 0) {
+#if defined(VERIFY_ON)
+ verify_enabled = true; // global in utils.h
+#endif
+ }
+ else if (std::strcmp(argv[i], "--verbose") == 0 ||
+ std::strcmp(argv[i], "-v") == 0) {
+#if defined(LOGGING_ON)
+ _log_level = LOG_INFO; // global in utils.h
+#endif
+ }
+ else if (i + 1 < argc && std::strcmp(argv[i], "--debug") == 0) {
+#if defined(DEBUG_ON)
+ _log_level = LOG_DEBUG; // global in utils.h
+ _log_category = argv[i + 1]; // global in utils.h
+ i++;
+#endif
+ }
+ else if (i + 1 < argc && std::strcmp(argv[i], "--trace") == 0) {
+#if defined(TRACING_ON)
+ _log_level = LOG_TRACE; // global in utils.h
+ try {
+ // global in utils.h
+ _trace_level = boost::lexical_cast<uint8_t>(argv[i + 1]);
+ }
+ catch (const boost::bad_lexical_cast& e) {
+ throw std::logic_error(_("Argument to --trace must be an integer"));
+ }
+ i++;
+#endif
+ }
+ }
+ }
+}
+
+} // namespace ledger
diff --git a/src/global.h b/src/global.h
new file mode 100644
index 00000000..ab3afed4
--- /dev/null
+++ b/src/global.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @file global.h
+ * @author John Wiegley
+ *
+ * @brief Contains the top-level functions used by main.cc
+ */
+#ifndef _GLOBAL_H
+#define _GLOBAL_H
+
+#include "interactive.h"
+#include "option.h"
+#include "report.h"
+
+namespace ledger {
+
+class session_t;
+class report_t;
+
+class global_scope_t : public noncopyable, public scope_t
+{
+ shared_ptr<session_t> session_ptr;
+ ptr_list<report_t> report_stack;
+
+public:
+ global_scope_t(char ** envp);
+ ~global_scope_t();
+
+ void read_init();
+ void read_environment_settings(char * envp[]);
+ strings_list read_command_arguments(scope_t& scope, strings_list args);
+ void normalize_session_options();
+ expr_t::func_t look_for_precommand(scope_t& scope, const string& verb);
+ expr_t::func_t look_for_command(scope_t& scope, const string& verb);
+
+ char * prompt_string();
+
+ session_t& session() {
+ return *session_ptr.get();
+ }
+ report_t& report() {
+ return report_stack.front();
+ }
+
+ void push_report() {
+ report_stack.push_front(new report_t(report_stack.front()));
+ scope_t::default_scope = &report();
+ }
+ void pop_report() {
+ assert(! report_stack.empty());
+ report_stack.pop_front();
+ // There should always be the "default report" waiting on the stack.
+ assert(! report_stack.empty());
+ scope_t::default_scope = &report();
+ }
+
+ void report_error(const std::exception& err);
+
+ /**
+ * @return \c true if a command was actually executed; otherwise, it probably
+ * just resulted in setting some options.
+ */
+ void execute_command(strings_list args, bool at_repl);
+ int execute_command_wrapper(strings_list args, bool at_repl);
+
+ value_t push_command(call_scope_t&) {
+ // Make a copy at position 2, because the topmost report object has an
+ // open output stream at this point. We want it to get popped off as
+ // soon as this command terminate so that the stream is closed cleanly.
+ report_stack.insert(++report_stack.begin(),
+ new report_t(report_stack.front()));
+ return true;
+ }
+ value_t pop_command(call_scope_t&) {
+ pop_report();
+ return true;
+ }
+
+ void show_version_info(std::ostream& out) {
+ out <<
+ "Ledger " << ledger::version << _(", the command-line accounting tool");
+ out <<
+ _("\n\nCopyright (c) 2003-2009, John Wiegley. All rights reserved.\n\n\
+This program is made available under the terms of the BSD Public License.\n\
+See LICENSE file included with the distribution for details and disclaimer.");
+ out << std::endl;
+ }
+
+ void report_options(report_t& report, std::ostream& out);
+
+ option_t<global_scope_t> * lookup_option(const char * p);
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
+
+ OPTION(global_scope_t, args_only);
+ OPTION(global_scope_t, debug_);
+
+ void visit_man_page() const;
+
+ OPTION_(global_scope_t, full_help, DO() { parent->visit_man_page(); }); // -H
+ OPTION_(global_scope_t, help, DO() { parent->visit_man_page(); }); // -h
+ OPTION_(global_scope_t, help_calc, DO() { parent->visit_man_page(); });
+ OPTION_(global_scope_t, help_comm, DO() { parent->visit_man_page(); });
+ OPTION_(global_scope_t, help_disp, DO() { parent->visit_man_page(); });
+
+ OPTION__
+ (global_scope_t, init_file_, // -i
+
+ CTOR(global_scope_t, init_file_) {
+ if (const char * home_var = std::getenv("HOME"))
+ on(none, (path(home_var) / ".ledgerrc").string());
+ else
+ on(none, path("./.ledgerrc").string());
+ });
+
+ OPTION(global_scope_t, options);
+ OPTION(global_scope_t, script_);
+ OPTION(global_scope_t, trace_);
+ OPTION(global_scope_t, verbose);
+ OPTION(global_scope_t, verify);
+
+ OPTION_(global_scope_t, version, DO() { // -v
+ parent->show_version_info(std::cout);
+ throw int(0); // exit immediately
+ });
+};
+
+void handle_debug_options(int argc, char * argv[]);
+
+} // namespace ledger
+
+#endif // _GLOBAL_H
diff --git a/src/interactive.cc b/src/interactive.cc
new file mode 100644
index 00000000..35382e8f
--- /dev/null
+++ b/src/interactive.cc
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "interactive.h"
+
+namespace ledger {
+
+void interactive_t::verify_arguments() const
+{
+ value_t::sequence_t::const_iterator i;
+
+ const char * p = spec.c_str();
+ const char * label = _("unknown");
+ bool wrong_arg = false;
+ bool dont_skip = false;
+ bool optional = *p == '&';
+ bool exit_loop = *p == '*';
+ std::size_t offset = 1;
+ bool is_seq = args.value().is_sequence();
+ const value_t * next_arg = NULL;
+ string vlabel;
+
+ if (is_seq) {
+ i = args.begin();
+ if (i != args.end())
+ next_arg = &(*i);
+ }
+ else if (! args.value().is_null()) {
+ next_arg = &args.value();
+ }
+
+ for (; ! wrong_arg && ! exit_loop && *p && next_arg; p++) {
+ DEBUG("interactive.verify",
+ "Want " << *p << " got: " << next_arg->label());
+
+ wrong_arg = false;
+ switch (*p) {
+ case 'a':
+ label = _("an amount");
+ wrong_arg = (! next_arg->is_long() &&
+ ! next_arg->is_amount() &&
+ ! next_arg->is_balance());
+ break;
+ case 'b':
+ label = _("a boolean");
+ wrong_arg = false; // booleans are converted
+ break;
+ case 'd':
+ label = _("a date");
+ wrong_arg = (! next_arg->is_date() &&
+ ! next_arg->is_datetime());
+ break;
+ case 't':
+ label = _("a date/time");
+ wrong_arg = (! next_arg->is_date() &&
+ ! next_arg->is_datetime());
+ break;
+ case 'i':
+ case 'l':
+ label = _("an integer");
+ if (next_arg->is_long() ||
+ (next_arg->is_amount() &&
+ ! next_arg->as_amount().has_commodity())) {
+ wrong_arg = false;
+ }
+ else if (next_arg->is_string()) {
+ wrong_arg = false;
+ for (const char * q = next_arg->as_string().c_str(); *q; q++) {
+ if (! std::isdigit(*q) && *q != '-') {
+ wrong_arg = true;
+ break;
+ }
+ }
+ }
+ else {
+ wrong_arg = true;
+ }
+ break;
+ case 'm':
+ label = _("a regex");
+ wrong_arg = ! next_arg->is_mask();
+ break;
+ case 's':
+ label = _("a string");
+ wrong_arg = ! next_arg->is_string();
+ break;
+ case 'v':
+ label = _("any value");
+ wrong_arg = false;
+ break;
+ case '^':
+ label = _("a scope");
+ wrong_arg = ! next_arg->is_scope();
+ break;
+ case 'S':
+ label = _("a sequence");
+ wrong_arg = false;
+ break;
+ case '&':
+ optional = true;
+ dont_skip = true;
+ break;
+ case '*':
+ optional = true;
+ exit_loop = true;
+ dont_skip = true;
+ break;
+ }
+ if (wrong_arg && optional && next_arg->is_null())
+ wrong_arg = false;
+
+ if (wrong_arg)
+ vlabel = next_arg->label();
+
+ if (! dont_skip) {
+ if (is_seq) {
+ if (++i != args.end()) {
+ next_arg = &(*i);
+ offset++;
+ } else {
+ next_arg = NULL;
+ }
+ } else {
+ next_arg = NULL;
+ }
+ }
+ dont_skip = false;
+ }
+
+ if (*p == '&' || *p == '*')
+ optional = true;
+
+ DEBUG("interactive.verify", "Remaining args are optional");
+
+ if (wrong_arg) {
+ throw_(std::logic_error,
+ _("Expected %1 for argument %2, but received %3")
+ << label << offset << vlabel);
+ }
+ else if (*p && ! optional && ! next_arg) {
+ throw_(std::logic_error, _("Too few arguments to function"));
+ }
+ else if (! *p && next_arg) {
+ throw_(std::logic_error, _("Too many arguments to function"));
+ }
+}
+
+string join_args(call_scope_t& args)
+{
+ std::ostringstream buf;
+ bool first = true;
+
+ for (std::size_t i = 0; i < args.size(); i++) {
+ if (first)
+ first = false;
+ else
+ buf << ' ';
+ buf << args[i];
+ }
+
+ return buf.str();
+}
+
+} // namespace ledger
diff --git a/src/interactive.h b/src/interactive.h
new file mode 100644
index 00000000..199b7b71
--- /dev/null
+++ b/src/interactive.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup expr
+ */
+
+/**
+ * @file interactive.h
+ * @author John Wiegley
+ *
+ * @ingroup expr
+ */
+#ifndef _INTERACTIVE_H
+#define _INTERACTIVE_H
+
+#include "scope.h"
+
+namespace ledger {
+
+class interactive_t : public noncopyable
+{
+ call_scope_t& args;
+ string spec;
+
+public:
+ explicit interactive_t(call_scope_t& _args, const string& _spec = "")
+ : args(_args), spec(_spec) {
+ TRACE_CTOR(interactive_t, "call_scope_t&, const string&");
+ verify_arguments();
+ }
+ virtual ~interactive_t() {
+ TRACE_DTOR(interactive_t);
+ }
+
+ void verify_arguments() const;
+
+ bool has(std::size_t index) const {
+ if (index < args.size() && ! args[index].is_null())
+ return true;
+ return false;
+ }
+
+ value_t& value_at(std::size_t index) {
+ assert(has(index));
+ return args[index];
+ }
+
+ template <typename T>
+ T get(std::size_t index);
+};
+
+template <>
+inline bool interactive_t::get<bool>(std::size_t index) {
+ return value_at(index).to_boolean();
+}
+template <>
+inline int interactive_t::get<int>(std::size_t index) {
+ return value_at(index).to_int();
+}
+template <>
+inline long interactive_t::get<long>(std::size_t index) {
+ return value_at(index).to_long();
+}
+template <>
+inline amount_t interactive_t::get<amount_t>(std::size_t index) {
+ return value_at(index).to_amount();
+}
+template <>
+inline string interactive_t::get<string>(std::size_t index) {
+ return value_at(index).to_string();
+}
+template <>
+inline mask_t interactive_t::get<mask_t>(std::size_t index) {
+ return value_at(index).to_mask();
+}
+template <>
+inline date_t interactive_t::get<date_t>(std::size_t index) {
+ return value_at(index).to_date();
+}
+template <>
+inline datetime_t interactive_t::get<datetime_t>(std::size_t index) {
+ return value_at(index).to_datetime();
+}
+template <>
+inline value_t::sequence_t&
+interactive_t::get<value_t::sequence_t&>(std::size_t index) {
+ return value_at(index).as_sequence_lval();
+}
+template <>
+inline const value_t::sequence_t&
+interactive_t::get<const value_t::sequence_t&>(std::size_t index) {
+ return value_at(index).as_sequence();
+}
+
+template <typename T>
+class in_context_t : public interactive_t
+{
+ T& context;
+
+public:
+ explicit in_context_t(call_scope_t& args, const string& spec)
+ : interactive_t(args, spec), context(find_scope<T>(args)) {
+ TRACE_CTOR(in_context_t, "call_scope_t&, const string&");
+ }
+ virtual ~in_context_t() {
+ TRACE_DTOR(in_context_t);
+ }
+
+ T& operator *() {
+ return context;
+ }
+ T * operator->() {
+ return &context;
+ }
+};
+
+string join_args(call_scope_t& args);
+
+} // namespace ledger
+
+#endif // _INTERACTIVE_H
+
diff --git a/src/item.cc b/src/item.cc
new file mode 100644
index 00000000..99d1d835
--- /dev/null
+++ b/src/item.cc
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "item.h"
+#include "interactive.h"
+
+namespace ledger {
+
+bool item_t::use_effective_date = false;
+
+bool item_t::has_tag(const string& tag) const
+{
+ DEBUG("item.meta", "Checking if item has tag: " << tag);
+ if (! metadata) {
+ DEBUG("item.meta", "Item has no metadata at all");
+ return false;
+ }
+ string_map::const_iterator i = metadata->find(tag);
+#if defined(DEBUG_ON)
+ if (SHOW_DEBUG("item.meta")) {
+ if (i == metadata->end())
+ DEBUG("item.meta", "Item does not have this tag");
+ else
+ DEBUG("item.meta", "Item has the tag!");
+ }
+#endif
+ return i != metadata->end();
+}
+
+bool item_t::has_tag(const mask_t& tag_mask,
+ const optional<mask_t>& value_mask) const
+{
+ if (metadata) {
+ foreach (const string_map::value_type& data, *metadata) {
+ if (tag_mask.match(data.first)) {
+ if (! value_mask)
+ return true;
+ else if (data.second)
+ return value_mask->match(*data.second);
+ }
+ }
+ }
+ return false;
+}
+
+optional<string> item_t::get_tag(const string& tag) const
+{
+ DEBUG("item.meta", "Getting item tag: " << tag);
+ if (metadata) {
+ DEBUG("item.meta", "Item has metadata");
+ string_map::const_iterator i = metadata->find(tag);
+ if (i != metadata->end()) {
+ DEBUG("item.meta", "Found the item!");
+ return (*i).second;
+ }
+ }
+ return none;
+}
+
+optional<string> item_t::get_tag(const mask_t& tag_mask,
+ const optional<mask_t>& value_mask) const
+{
+ if (metadata) {
+ foreach (const string_map::value_type& data, *metadata) {
+ if (tag_mask.match(data.first) &&
+ (! value_mask ||
+ (data.second && value_mask->match(*data.second))))
+ return data.second;
+ }
+ }
+ return none;
+}
+
+void item_t::set_tag(const string& tag,
+ const optional<string>& value)
+{
+ if (! metadata)
+ metadata = string_map();
+
+ DEBUG("item.meta", "Setting tag '" << tag << "' to value '"
+ << (value ? *value : string("<none>")) << "'");
+
+ std::pair<string_map::iterator, bool> result
+ = metadata->insert(string_map::value_type(tag, value));
+ assert(result.second);
+}
+
+void item_t::parse_tags(const char * p,
+ optional<date_t::year_type> current_year)
+{
+ if (const char * b = std::strchr(p, '[')) {
+ if (*(b + 1) != '\0' &&
+ (std::isdigit(*(b + 1)) || *(b + 1) == '=')) {
+ if (const char * e = std::strchr(p, ']')) {
+ char buf[256];
+ std::strncpy(buf, b + 1, e - b - 1);
+ buf[e - b - 1] = '\0';
+
+ if (char * p = std::strchr(buf, '=')) {
+ *p++ = '\0';
+ _date_eff = parse_date(p, current_year);
+ }
+ if (buf[0])
+ _date = parse_date(buf, current_year);
+ }
+ }
+ }
+
+ if (! std::strchr(p, ':'))
+ return;
+
+ scoped_array<char> buf(new char[std::strlen(p) + 1]);
+
+ std::strcpy(buf.get(), p);
+
+ string tag;
+ for (char * q = std::strtok(buf.get(), " \t");
+ q;
+ q = std::strtok(NULL, " \t")) {
+ const string::size_type len = std::strlen(q);
+ if (! tag.empty()) {
+ if (! has_tag(tag))
+ set_tag(tag, string(p + (q - buf.get())));
+ break;
+ }
+ else if (q[0] == ':' && q[len - 1] == ':') { // a series of tags
+ for (char * r = std::strtok(q + 1, ":");
+ r;
+ r = std::strtok(NULL, ":"))
+ set_tag(r);
+ }
+ else if (q[len - 1] == ':') { // a metadata setting
+ tag = string(q, len - 1);
+ }
+ }
+}
+
+void item_t::append_note(const char * p,
+ optional<date_t::year_type> current_year)
+{
+ if (note) {
+ *note += '\n';
+ *note += p;
+ } else {
+ note = p;
+ }
+
+ parse_tags(p, current_year);
+}
+
+namespace {
+ value_t get_status(item_t& item) {
+ return long(item.state());
+ }
+ value_t get_uncleared(item_t& item) {
+ return item.state() == item_t::UNCLEARED;
+ }
+ value_t get_cleared(item_t& item) {
+ return item.state() == item_t::CLEARED;
+ }
+ value_t get_pending(item_t& item) {
+ return item.state() == item_t::PENDING;
+ }
+
+ value_t get_actual(item_t& item) {
+ return ! item.has_flags(ITEM_GENERATED | ITEM_TEMP);
+ }
+
+ value_t get_date(item_t& item) {
+ return item.date();
+ }
+ value_t get_effective_date(item_t& item) {
+ if (optional<date_t> effective = item.effective_date())
+ return *effective;
+ return NULL_VALUE;
+ }
+ value_t get_note(item_t& item) {
+ return string_value(item.note ? *item.note : empty_string);
+ }
+
+ value_t has_tag(call_scope_t& args) {
+ item_t& item(find_scope<item_t>(args));
+
+ if (args.size() == 1) {
+ if (args[0].is_string())
+ return item.has_tag(args[0].as_string());
+ else if (args[0].is_mask())
+ return item.has_tag(args[0].as_mask());
+ else
+ throw_(std::runtime_error,
+ _("Expected string or mask for argument 1, but received %1")
+ << args[0].label());
+ }
+ else if (args.size() == 2) {
+ if (args[0].is_mask() && args[1].is_mask())
+ return item.has_tag(args[0].to_mask(), args[1].to_mask());
+ else
+ throw_(std::runtime_error,
+ _("Expected masks for arguments 1 and 2, but received %1 and %2")
+ << args[0].label() << args[1].label());
+ }
+ else if (args.size() == 0) {
+ throw_(std::runtime_error, _("Too few arguments to function"));
+ }
+ else {
+ throw_(std::runtime_error, _("Too many arguments to function"));
+ }
+ return false;
+ }
+
+ value_t get_tag(call_scope_t& scope) {
+ in_context_t<item_t> env(scope, "s");
+ if (optional<string> value = env->get_tag(env.get<string>(0)))
+ return string_value(*value);
+ return string_value(empty_string);
+ }
+
+ value_t get_pathname(item_t& item) {
+ if (item.pos)
+ return string_value(item.pos->pathname.string());
+ else
+ return string_value(empty_string);
+ }
+
+ value_t get_beg_pos(item_t& item) {
+ return item.pos ? long(item.pos->beg_pos) : 0L;
+ }
+
+ value_t get_beg_line(item_t& item) {
+ return item.pos ? long(item.pos->beg_line) : 0L;
+ }
+
+ value_t get_end_pos(item_t& item) {
+ return item.pos ? long(item.pos->end_pos) : 0L;
+ }
+
+ value_t get_end_line(item_t& item) {
+ return item.pos ? long(item.pos->end_line) : 0L;
+ }
+
+ value_t get_depth(item_t&) {
+ return 0L;
+ }
+
+ value_t ignore(item_t&) {
+ return false;
+ }
+
+ template <value_t (*Func)(item_t&)>
+ value_t get_wrapper(call_scope_t& scope) {
+ return (*Func)(find_scope<item_t>(scope));
+ }
+}
+
+value_t get_comment(item_t& item)
+{
+ if (! item.note) {
+ return string_value("");
+ } else {
+ std::ostringstream buf;
+ if (item.note->length() > 15)
+ buf << "\n ;";
+ else
+ buf << " ;";
+
+ bool need_separator = false;
+ for (const char * p = item.note->c_str(); *p; p++) {
+ if (*p == '\n') {
+ need_separator = true;
+ } else {
+ if (need_separator) {
+ buf << "\n ;";
+ need_separator = false;
+ }
+ buf << *p;
+ }
+ }
+ return string_value(buf.str());
+ }
+}
+
+expr_t::ptr_op_t item_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
+{
+ if (kind != symbol_t::FUNCTION)
+ return NULL;
+
+ switch (name[0]) {
+ case 'a':
+ if (name == "actual")
+ return WRAP_FUNCTOR(get_wrapper<&get_actual>);
+ break;
+
+ case 'b':
+ if (name == "beg_line")
+ return WRAP_FUNCTOR(get_wrapper<&get_beg_line>);
+ else if (name == "beg_pos")
+ return WRAP_FUNCTOR(get_wrapper<&get_beg_pos>);
+ break;
+
+ case 'c':
+ if (name == "cleared")
+ return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
+ else if (name == "comment")
+ return WRAP_FUNCTOR(get_wrapper<&get_comment>);
+ break;
+
+ case 'd':
+ if (name[1] == '\0' || name == "date")
+ return WRAP_FUNCTOR(get_wrapper<&get_date>);
+ else if (name == "depth")
+ return WRAP_FUNCTOR(get_wrapper<&get_depth>);
+ break;
+
+ case 'e':
+ if (name == "end_line")
+ return WRAP_FUNCTOR(get_wrapper<&get_end_line>);
+ else if (name == "end_pos")
+ return WRAP_FUNCTOR(get_wrapper<&get_end_pos>);
+ else if (name == "effective_date")
+ return WRAP_FUNCTOR(get_wrapper<&get_effective_date>);
+ break;
+
+ case 'f':
+ if (name == "filename")
+ return WRAP_FUNCTOR(get_wrapper<&get_pathname>);
+ break;
+
+ case 'h':
+ if (name == "has_tag")
+ return WRAP_FUNCTOR(ledger::has_tag);
+ else if (name == "has_meta")
+ return WRAP_FUNCTOR(ledger::has_tag);
+ break;
+
+ case 'i':
+ if (name == "is_account")
+ return WRAP_FUNCTOR(get_wrapper<&ignore>);
+ break;
+
+ case 'm':
+ if (name == "meta")
+ return WRAP_FUNCTOR(ledger::get_tag);
+ break;
+
+ case 'n':
+ if (name == "note")
+ return WRAP_FUNCTOR(get_wrapper<&get_note>);
+ break;
+
+ case 'p':
+ if (name == "pending")
+ return WRAP_FUNCTOR(get_wrapper<&get_pending>);
+ else if (name == "parent")
+ return WRAP_FUNCTOR(get_wrapper<&ignore>);
+ break;
+
+ case 's':
+ if (name == "status")
+ return WRAP_FUNCTOR(get_wrapper<&get_status>);
+ break;
+
+ case 't':
+ if (name == "tag")
+ return WRAP_FUNCTOR(ledger::get_tag);
+ break;
+
+ case 'u':
+ if (name == "uncleared")
+ return WRAP_FUNCTOR(get_wrapper<&get_uncleared>);
+ break;
+
+ case 'L':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_actual>);
+ break;
+
+ case 'X':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
+ break;
+
+ case 'Y':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_pending>);
+ break;
+ }
+
+ return NULL;
+}
+
+bool item_t::valid() const
+{
+ if (_state != UNCLEARED && _state != CLEARED && _state != PENDING) {
+ DEBUG("ledger.validate", "item_t: state is bad");
+ return false;
+ }
+
+ return true;
+}
+
+void print_item(std::ostream& out, const item_t& item, const string& prefix)
+{
+ out << source_context(item.pos->pathname, item.pos->beg_pos,
+ item.pos->end_pos, prefix);
+}
+
+string item_context(const item_t& item, const string& desc)
+{
+ std::streamoff len = item.pos->end_pos - item.pos->beg_pos;
+ if (! len)
+ return _("<no item context>");
+
+ assert(len > 0);
+ assert(len < 2048);
+
+ std::ostringstream out;
+
+ if (item.pos->pathname == path("/dev/stdin")) {
+ out << desc << _(" from standard input:");
+ return out.str();
+ }
+
+ out << desc << _(" from \"") << item.pos->pathname.string() << "\"";
+
+ if (item.pos->beg_line != item.pos->end_line)
+ out << _(", lines ") << item.pos->beg_line << "-"
+ << item.pos->end_line << ":\n";
+ else
+ out << _(", line ") << item.pos->beg_line << ":\n";
+
+ print_item(out, item, "> ");
+
+ return out.str();
+}
+
+} // namespace ledger
diff --git a/src/item.h b/src/item.h
new file mode 100644
index 00000000..84385eb7
--- /dev/null
+++ b/src/item.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @defgroup data Data representation
+ */
+
+/**
+ * @file item.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _ITEM_H
+#define _ITEM_H
+
+#include "scope.h"
+
+namespace ledger {
+
+struct position_t
+{
+ path pathname;
+ istream_pos_type beg_pos;
+ std::size_t beg_line;
+ istream_pos_type end_pos;
+ std::size_t end_line;
+
+ position_t() : beg_pos(0), beg_line(0), end_pos(0), end_line(0) {
+ TRACE_CTOR(position_t, "");
+ }
+ position_t(const position_t& pos) {
+ TRACE_CTOR(position_t, "copy");
+ *this = pos;
+ }
+ ~position_t() throw() {
+ TRACE_DTOR(position_t);
+ }
+
+ position_t& operator=(const position_t& pos) {
+ if (this != &pos) {
+ pathname = pos.pathname;
+ beg_pos = pos.beg_pos;
+ beg_line = pos.beg_line;
+ end_pos = pos.end_pos;
+ end_line = pos.end_line;
+ }
+ return *this;
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & pathname;
+ ar & beg_pos;
+ ar & beg_line;
+ ar & end_pos;
+ ar & end_line;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class item_t : public supports_flags<>, public scope_t
+{
+public:
+#define ITEM_NORMAL 0x00 // no flags at all, a basic posting
+#define ITEM_GENERATED 0x01 // posting was not found in a journal
+#define ITEM_TEMP 0x02 // posting is a managed temporary
+
+ enum state_t { UNCLEARED = 0, CLEARED, PENDING };
+
+ typedef std::map<string, optional<string> > string_map;
+
+ state_t _state;
+ optional<date_t> _date;
+ optional<date_t> _date_eff;
+ optional<string> note;
+ optional<position_t> pos;
+ optional<string_map> metadata;
+
+ item_t(flags_t _flags = ITEM_NORMAL, const optional<string>& _note = none)
+ : supports_flags<>(_flags), _state(UNCLEARED), note(_note)
+ {
+ TRACE_CTOR(item_t, "flags_t, const string&");
+ }
+ item_t(const item_t& item) : supports_flags<>(), scope_t()
+ {
+ TRACE_CTOR(item_t, "copy");
+ copy_details(item);
+ }
+ virtual ~item_t() {
+ TRACE_DTOR(item_t);
+ }
+
+ void copy_details(const item_t& item)
+ {
+ set_flags(item.flags());
+ set_state(item.state());
+
+ _date = item._date;
+ _date_eff = item._date_eff;
+ note = item.note;
+ pos = item.pos;
+ metadata = item.metadata;
+ }
+
+ virtual bool operator==(const item_t& xact) {
+ return this == &xact;
+ }
+ virtual bool operator!=(const item_t& xact) {
+ return ! (*this == xact);
+ }
+
+ virtual bool has_tag(const string& tag) const;
+ virtual bool has_tag(const mask_t& tag_mask,
+ const optional<mask_t>& value_mask = none) const;
+
+ virtual optional<string> get_tag(const string& tag) const;
+ virtual optional<string> get_tag(const mask_t& tag_mask,
+ const optional<mask_t>& value_mask = none) const;
+
+ virtual void set_tag(const string& tag,
+ const optional<string>& value = none);
+
+ virtual void parse_tags(const char * p,
+ optional<date_t::year_type> current_year = none);
+ virtual void append_note(const char * p,
+ optional<date_t::year_type> current_year = none);
+
+ static bool use_effective_date;
+
+ virtual date_t date() const {
+ assert(_date);
+ if (use_effective_date)
+ if (optional<date_t> effective = effective_date())
+ return *effective;
+ return *_date;
+ }
+ virtual optional<date_t> effective_date() const {
+ return _date_eff;
+ }
+
+ void set_state(state_t new_state) {
+ _state = new_state;
+ }
+ virtual state_t state() const {
+ return _state;
+ }
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
+
+ bool valid() const;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<supports_flags<> >(*this);
+ ar & boost::serialization::base_object<scope_t>(*this);
+ ar & _state;
+ ar & _date;
+ ar & _date_eff;
+ ar & note;
+ ar & pos;
+ ar & metadata;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+value_t get_comment(item_t& item);
+void print_item(std::ostream& out, const item_t& item,
+ const string& prefix = "");
+string item_context(const item_t& item, const string& desc);
+
+} // namespace ledger
+
+#endif // _ITEM_H
diff --git a/src/iterators.cc b/src/iterators.cc
new file mode 100644
index 00000000..540ba8ae
--- /dev/null
+++ b/src/iterators.cc
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "iterators.h"
+#include "journal.h"
+#include "compare.h"
+
+namespace ledger {
+
+void xacts_iterator::reset(journal_t& journal)
+{
+ xacts_i = journal.xacts.begin();
+ xacts_end = journal.xacts.end();
+ xacts_uninitialized = false;
+}
+
+xact_t * xacts_iterator::operator()()
+{
+ if (xacts_i != xacts_end)
+ return *xacts_i++;
+ else
+ return NULL;
+}
+
+void journal_posts_iterator::reset(journal_t& journal)
+{
+ xacts.reset(journal);
+
+ xact_t * xact = xacts();
+ if (xact != NULL)
+ posts.reset(*xact);
+}
+
+post_t * journal_posts_iterator::operator()()
+{
+ post_t * post = posts();
+ if (post == NULL) {
+ xact_t * xact = xacts();
+ if (xact != NULL) {
+ posts.reset(*xact);
+ post = posts();
+ }
+ }
+ return post;
+}
+
+void posts_commodities_iterator::reset(journal_t& journal)
+{
+ journal_posts.reset(journal);
+
+ std::set<commodity_t *> commodities;
+
+ for (post_t * post = journal_posts(); post; post = journal_posts()) {
+ commodity_t& comm(post->amount.commodity());
+ if (comm.flags() & COMMODITY_NOMARKET)
+ continue;
+ commodities.insert(&comm);
+ }
+
+ std::map<string, xact_t *> xacts_by_commodity;
+
+ foreach (commodity_t * comm, commodities) {
+ if (optional<commodity_t::varied_history_t&> history =
+ comm->varied_history()) {
+ account_t * account = journal.master->find_account(comm->symbol());
+
+ foreach (commodity_t::history_by_commodity_map::value_type pair,
+ history->histories) {
+ foreach (commodity_t::history_map::value_type hpair,
+ pair.second.prices) {
+ xact_t * xact;
+ string symbol = hpair.second.commodity().symbol();
+
+ std::map<string, xact_t *>::iterator i =
+ xacts_by_commodity.find(symbol);
+ if (i != xacts_by_commodity.end()) {
+ xact = (*i).second;
+ } else {
+ xact = &temps.create_xact();
+ xact_temps.push_back(xact);
+ xact->payee = symbol;
+ xact->_date = hpair.first.date();
+ xacts_by_commodity.insert
+ (std::pair<string, xact_t *>(symbol, xact));
+ }
+
+ bool post_already_exists = false;
+
+ foreach (post_t * post, xact->posts) {
+ if (post->_date == hpair.first.date() &&
+ post->amount == hpair.second) {
+ post_already_exists = true;
+ break;
+ }
+ }
+
+ if (! post_already_exists) {
+ post_t& temp = temps.create_post(*xact, account);
+ temp._date = hpair.first.date();
+ temp.amount = hpair.second;
+
+ temp.xdata().datetime = hpair.first;
+ }
+ }
+ }
+ }
+ }
+
+ xacts.xacts_i = xact_temps.begin();
+ xacts.xacts_end = xact_temps.end();
+
+ xacts.xacts_uninitialized = false;
+
+ xact_t * xact = xacts();
+ if (xact != NULL)
+ posts.reset(*xact);
+}
+
+post_t * posts_commodities_iterator::operator()()
+{
+ post_t * post = posts();
+ if (post == NULL) {
+ xact_t * xact = xacts();
+ if (xact != NULL) {
+ posts.reset(*xact);
+ post = posts();
+ }
+ }
+ return post;
+}
+
+account_t * basic_accounts_iterator::operator()()
+{
+ while (! accounts_i.empty() &&
+ accounts_i.back() == accounts_end.back()) {
+ accounts_i.pop_back();
+ accounts_end.pop_back();
+ }
+ if (accounts_i.empty())
+ return NULL;
+
+ account_t * account = (*(accounts_i.back()++)).second;
+ assert(account);
+
+ // If this account has children, queue them up to be iterated next.
+ if (! account->accounts.empty())
+ push_back(*account);
+
+ return account;
+}
+
+void sorted_accounts_iterator::push_back(account_t& account)
+{
+ accounts_list.push_back(accounts_deque_t());
+
+ if (flatten_all) {
+ push_all(account, accounts_list.back());
+
+ std::stable_sort(accounts_list.back().begin(),
+ accounts_list.back().end(),
+ compare_items<account_t>(sort_cmp));
+
+#if defined(DEBUG_ON)
+ if (SHOW_DEBUG("accounts.sorted")) {
+ foreach (account_t * account, accounts_list.back())
+ DEBUG("accounts.sorted",
+ "Account (flat): " << account->fullname());
+ }
+#endif
+ } else {
+ sort_accounts(account, accounts_list.back());
+ }
+
+ sorted_accounts_i.push_back(accounts_list.back().begin());
+ sorted_accounts_end.push_back(accounts_list.back().end());
+}
+
+void sorted_accounts_iterator::push_all(account_t& account,
+ accounts_deque_t& deque)
+{
+ foreach (accounts_map::value_type& pair, account.accounts) {
+ deque.push_back(pair.second);
+ push_all(*pair.second, deque);
+ }
+}
+
+void sorted_accounts_iterator::sort_accounts(account_t& account,
+ accounts_deque_t& deque)
+{
+ foreach (accounts_map::value_type& pair, account.accounts)
+ deque.push_back(pair.second);
+
+ std::stable_sort(deque.begin(), deque.end(),
+ compare_items<account_t>(sort_cmp));
+
+#if defined(DEBUG_ON)
+ if (SHOW_DEBUG("accounts.sorted")) {
+ foreach (account_t * account, deque)
+ DEBUG("accounts.sorted", "Account: " << account->fullname());
+ }
+#endif
+}
+
+account_t * sorted_accounts_iterator::operator()()
+{
+ while (! sorted_accounts_i.empty() &&
+ sorted_accounts_i.back() == sorted_accounts_end.back()) {
+ sorted_accounts_i.pop_back();
+ sorted_accounts_end.pop_back();
+ assert(! accounts_list.empty());
+ accounts_list.pop_back();
+ }
+ if (sorted_accounts_i.empty())
+ return NULL;
+
+ account_t * account = *sorted_accounts_i.back()++;
+ assert(account);
+
+ // If this account has children, queue them up to be iterated next.
+ if (! flatten_all && ! account->accounts.empty())
+ push_back(*account);
+
+ // Make sure the sorting value gets recalculated for this account
+ account->xdata().drop_flags(ACCOUNT_EXT_SORT_CALC);
+ return account;
+}
+
+} // namespace ledger
diff --git a/src/iterators.h b/src/iterators.h
new file mode 100644
index 00000000..1cbe4c25
--- /dev/null
+++ b/src/iterators.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup data
+ */
+
+/**
+ * @file iterators.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _ITERATORS_H
+#define _ITERATORS_H
+
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "temps.h"
+
+namespace ledger {
+
+class journal_t;
+
+class posts_iterator : public noncopyable
+{
+public:
+ virtual ~posts_iterator() throw() {}
+ virtual post_t * operator()() = 0;
+};
+
+class xact_posts_iterator : public posts_iterator
+{
+ posts_list::iterator posts_i;
+ posts_list::iterator posts_end;
+
+ bool posts_uninitialized;
+
+public:
+ xact_posts_iterator() : posts_uninitialized(true) {
+ TRACE_CTOR(xact_posts_iterator, "");
+ }
+ xact_posts_iterator(xact_t& xact)
+ : posts_uninitialized(true) {
+ TRACE_CTOR(xact_posts_iterator, "xact_t&");
+ reset(xact);
+ }
+ virtual ~xact_posts_iterator() throw() {
+ TRACE_DTOR(xact_posts_iterator);
+ }
+
+ void reset(xact_t& xact) {
+ posts_i = xact.posts.begin();
+ posts_end = xact.posts.end();
+
+ posts_uninitialized = false;
+ }
+
+ virtual post_t * operator()() {
+ if (posts_uninitialized || posts_i == posts_end)
+ return NULL;
+ return *posts_i++;
+ }
+};
+
+class xacts_iterator : public noncopyable
+{
+public:
+ xacts_list::iterator xacts_i;
+ xacts_list::iterator xacts_end;
+
+ bool xacts_uninitialized;
+
+ xacts_iterator() : xacts_uninitialized(true) {
+ TRACE_CTOR(xacts_iterator, "");
+ }
+ xacts_iterator(journal_t& journal) : xacts_uninitialized(true) {
+ TRACE_CTOR(xacts_iterator, "journal_t&");
+ reset(journal);
+ }
+ virtual ~xacts_iterator() throw() {
+ TRACE_DTOR(xacts_iterator);
+ }
+
+ void reset(journal_t& journal);
+
+ xact_t * operator()();
+};
+
+class journal_posts_iterator : public posts_iterator
+{
+ xacts_iterator xacts;
+ xact_posts_iterator posts;
+
+public:
+ journal_posts_iterator() {
+ TRACE_CTOR(journal_posts_iterator, "");
+ }
+ journal_posts_iterator(journal_t& journal) {
+ TRACE_CTOR(journal_posts_iterator, "journal_t&");
+ reset(journal);
+ }
+ virtual ~journal_posts_iterator() throw() {
+ TRACE_DTOR(journal_posts_iterator);
+ }
+
+ void reset(journal_t& journal);
+
+ virtual post_t * operator()();
+};
+
+class posts_commodities_iterator : public posts_iterator
+{
+protected:
+ journal_posts_iterator journal_posts;
+ xacts_iterator xacts;
+ xact_posts_iterator posts;
+ temporaries_t temps;
+ xacts_list xact_temps;
+
+public:
+ posts_commodities_iterator() {
+ TRACE_CTOR(posts_commodities_iterator, "");
+ }
+ posts_commodities_iterator(journal_t& journal) {
+ TRACE_CTOR(posts_commodities_iterator, "journal_t&");
+ reset(journal);
+ }
+ virtual ~posts_commodities_iterator() throw() {
+ TRACE_DTOR(posts_commodities_iterator);
+ }
+
+ void reset(journal_t& journal);
+
+ virtual post_t * operator()();
+};
+
+class accounts_iterator : public noncopyable
+{
+public:
+ virtual ~accounts_iterator() throw() {}
+ virtual account_t * operator()() = 0;
+};
+
+class basic_accounts_iterator : public accounts_iterator
+{
+ std::list<accounts_map::const_iterator> accounts_i;
+ std::list<accounts_map::const_iterator> accounts_end;
+
+public:
+ basic_accounts_iterator() {
+ TRACE_CTOR(basic_accounts_iterator, "");
+ }
+ basic_accounts_iterator(account_t& account) {
+ TRACE_CTOR(basic_accounts_iterator, "account_t&");
+ push_back(account);
+ }
+ virtual ~basic_accounts_iterator() throw() {
+ TRACE_DTOR(basic_accounts_iterator);
+ }
+
+ void push_back(account_t& account) {
+ accounts_i.push_back(account.accounts.begin());
+ accounts_end.push_back(account.accounts.end());
+ }
+
+ virtual account_t * operator()();
+};
+
+class sorted_accounts_iterator : public accounts_iterator
+{
+ expr_t sort_cmp;
+ bool flatten_all;
+
+ typedef std::deque<account_t *> accounts_deque_t;
+
+ std::list<accounts_deque_t> accounts_list;
+ std::list<accounts_deque_t::const_iterator> sorted_accounts_i;
+ std::list<accounts_deque_t::const_iterator> sorted_accounts_end;
+
+public:
+ sorted_accounts_iterator(account_t& account,
+ const expr_t& _sort_cmp, bool _flatten_all)
+ : sort_cmp(_sort_cmp), flatten_all(_flatten_all) {
+ TRACE_CTOR(sorted_accounts_iterator, "const expr_t&, bool, account_t&");
+ push_back(account);
+ }
+ virtual ~sorted_accounts_iterator() throw() {
+ TRACE_DTOR(sorted_accounts_iterator);
+ }
+
+ void push_back(account_t& account);
+ void push_all(account_t& account, accounts_deque_t& deque);
+ void sort_accounts(account_t& account, accounts_deque_t& deque);
+
+ virtual account_t * operator()();
+};
+
+} // namespace ledger
+
+#endif // _ITERATORS_H
diff --git a/src/journal.cc b/src/journal.cc
new file mode 100644
index 00000000..6ebccd66
--- /dev/null
+++ b/src/journal.cc
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "journal.h"
+#include "amount.h"
+#include "commodity.h"
+#include "pool.h"
+#include "xact.h"
+#include "account.h"
+
+namespace ledger {
+
+journal_t::journal_t()
+{
+ TRACE_CTOR(journal_t, "");
+ initialize();
+}
+
+journal_t::journal_t(const path& pathname)
+{
+ TRACE_CTOR(journal_t, "path");
+ initialize();
+ read(pathname);
+}
+
+journal_t::journal_t(const string& str)
+{
+ TRACE_CTOR(journal_t, "string");
+ initialize();
+ read(str);
+}
+
+journal_t::~journal_t()
+{
+ TRACE_DTOR(journal_t);
+
+ // Don't bother unhooking each xact's posts from the
+ // accounts they refer to, because all accounts are about to
+ // be deleted.
+ foreach (xact_t * xact, xacts)
+ checked_delete(xact);
+
+ foreach (auto_xact_t * xact, auto_xacts)
+ checked_delete(xact);
+
+ foreach (period_xact_t * xact, period_xacts)
+ checked_delete(xact);
+
+ checked_delete(master);
+}
+
+void journal_t::initialize()
+{
+ master = new account_t;
+ bucket = NULL;
+ was_loaded = false;
+}
+
+void journal_t::add_account(account_t * acct)
+{
+ master->add_account(acct);
+}
+
+bool journal_t::remove_account(account_t * acct)
+{
+ return master->remove_account(acct);
+}
+
+account_t * journal_t::find_account(const string& name, bool auto_create)
+{
+ return master->find_account(name, auto_create);
+}
+
+account_t * journal_t::find_account_re(const string& regexp)
+{
+ return master->find_account_re(regexp);
+}
+
+bool journal_t::add_xact(xact_t * xact)
+{
+ xact->journal = this;
+
+ if (! xact->finalize()) {
+ xact->journal = NULL;
+ return false;
+ }
+
+ extend_xact(xact);
+ xacts.push_back(xact);
+
+ return true;
+}
+
+void journal_t::extend_xact(xact_base_t * xact)
+{
+ foreach (auto_xact_t * auto_xact, auto_xacts)
+ auto_xact->extend_xact(*xact);
+}
+
+bool journal_t::remove_xact(xact_t * xact)
+{
+ bool found = false;
+ xacts_list::iterator i;
+ for (i = xacts.begin(); i != xacts.end(); i++)
+ if (*i == xact) {
+ found = true;
+ break;
+ }
+ if (! found)
+ return false;
+
+ xacts.erase(i);
+ xact->journal = NULL;
+
+ return true;
+}
+
+std::size_t journal_t::read(std::istream& in,
+ const path& pathname,
+ account_t * master_alt,
+ scope_t * scope)
+{
+ std::size_t count = 0;
+ try {
+ if (! scope)
+ scope = scope_t::default_scope;
+
+ if (! scope)
+ throw_(std::runtime_error,
+ _("No default scope in which to read journal file '%1'")
+ << pathname);
+
+ value_t strict = expr_t("strict").calc(*scope);
+
+ count = parse(in, *scope, master_alt ? master_alt : master,
+ &pathname, strict.to_boolean());
+ }
+ catch (...) {
+ clear_xdata();
+ throw;
+ }
+
+ // xdata may have been set for some accounts and transaction due to the use
+ // of balance assertions or other calculations performed in valexpr-based
+ // posting amounts.
+ clear_xdata();
+
+ return count;
+}
+
+std::size_t journal_t::read(const path& pathname,
+ account_t * master,
+ scope_t * scope)
+{
+ path filename = resolve_path(pathname);
+
+ if (! exists(filename))
+ throw_(std::runtime_error,
+ _("Cannot read journal file '%1'") << filename);
+
+ ifstream stream(filename);
+ std::size_t count = read(stream, filename, master, scope);
+ if (count > 0)
+ sources.push_back(fileinfo_t(filename));
+ return count;
+}
+
+bool journal_t::has_xdata()
+{
+ foreach (xact_t * xact, xacts)
+ if (xact->has_xdata())
+ return true;
+
+ foreach (auto_xact_t * xact, auto_xacts)
+ if (xact->has_xdata())
+ return true;
+
+ foreach (period_xact_t * xact, period_xacts)
+ if (xact->has_xdata())
+ return true;
+
+ if (master->has_xdata() || master->children_with_xdata())
+ return true;
+
+ return false;
+}
+
+void journal_t::clear_xdata()
+{
+ foreach (xact_t * xact, xacts)
+ if (! xact->has_flags(ITEM_TEMP))
+ xact->clear_xdata();
+
+ foreach (auto_xact_t * xact, auto_xacts)
+ if (! xact->has_flags(ITEM_TEMP))
+ xact->clear_xdata();
+
+ foreach (period_xact_t * xact, period_xacts)
+ if (! xact->has_flags(ITEM_TEMP))
+ xact->clear_xdata();
+
+ master->clear_xdata();
+}
+
+bool journal_t::valid() const
+{
+ if (! master->valid()) {
+ DEBUG("ledger.validate", "journal_t: master not valid");
+ return false;
+ }
+
+ foreach (const xact_t * xact, xacts)
+ if (! xact->valid()) {
+ DEBUG("ledger.validate", "journal_t: xact not valid");
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace ledger
diff --git a/src/journal.h b/src/journal.h
new file mode 100644
index 00000000..8d59e3b4
--- /dev/null
+++ b/src/journal.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup data
+ */
+
+/**
+ * @file journal.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _JOURNAL_H
+#define _JOURNAL_H
+
+#include "utils.h"
+#include "times.h"
+
+namespace ledger {
+
+class xact_base_t;
+class xact_t;
+class auto_xact_t;
+class period_xact_t;
+class account_t;
+class scope_t;
+
+typedef std::list<xact_t *> xacts_list;
+typedef std::list<auto_xact_t *> auto_xacts_list;
+typedef std::list<period_xact_t *> period_xacts_list;
+
+class journal_t : public noncopyable
+{
+public:
+ struct fileinfo_t
+ {
+ optional<path> filename;
+ uintmax_t size;
+ datetime_t modtime;
+ bool from_stream;
+
+ fileinfo_t() : size(0), from_stream(true) {
+ TRACE_CTOR(journal_t::fileinfo_t, "");
+ }
+ fileinfo_t(const path& _filename)
+ : filename(_filename), from_stream(false) {
+ TRACE_CTOR(journal_t::fileinfo_t, "const path&");
+ size = file_size(*filename);
+ modtime = posix_time::from_time_t(last_write_time(*filename));
+ }
+ fileinfo_t(const fileinfo_t& info)
+ : filename(info.filename), size(info.size),
+ modtime(info.modtime), from_stream(info.from_stream)
+ {
+ TRACE_CTOR(journal_t::fileinfo_t, "copy");
+ }
+ ~fileinfo_t() throw() {
+ TRACE_DTOR(journal_t::fileinfo_t);
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+ private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & filename;
+ ar & size;
+ ar & modtime;
+ ar & from_stream;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+ };
+
+ account_t * master;
+ account_t * bucket;
+ xacts_list xacts;
+ auto_xacts_list auto_xacts;
+ period_xacts_list period_xacts;
+ std::list<fileinfo_t> sources;
+ bool was_loaded;
+
+ journal_t();
+ journal_t(const path& pathname);
+ journal_t(const string& str);
+ ~journal_t();
+
+ void initialize();
+
+ std::list<fileinfo_t>::iterator sources_begin() {
+ return sources.begin();
+ }
+ std::list<fileinfo_t>::iterator sources_end() {
+ return sources.end();
+ }
+
+ // These four methods are delegated to the current session, since all
+ // accounts processed are gathered together at the session level.
+ void add_account(account_t * acct);
+ bool remove_account(account_t * acct);
+ account_t * find_account(const string& name, bool auto_create = true);
+ account_t * find_account_re(const string& regexp);
+
+ bool add_xact(xact_t * xact);
+ void extend_xact(xact_base_t * xact);
+ bool remove_xact(xact_t * xact);
+
+ xacts_list::iterator xacts_begin() {
+ return xacts.begin();
+ }
+ xacts_list::iterator xacts_end() {
+ return xacts.end();
+ }
+ auto_xacts_list::iterator auto_xacts_begin() {
+ return auto_xacts.begin();
+ }
+ auto_xacts_list::iterator auto_xacts_end() {
+ return auto_xacts.end();
+ }
+ period_xacts_list::iterator period_xacts_begin() {
+ return period_xacts.begin();
+ }
+ period_xacts_list::iterator period_xacts_end() {
+ return period_xacts.end();
+ }
+
+ std::size_t read(std::istream& in,
+ const path& pathname,
+ account_t * master = NULL,
+ scope_t * scope = NULL);
+ std::size_t read(const path& pathname,
+ account_t * master = NULL,
+ scope_t * scope = NULL);
+
+ std::size_t parse(std::istream& in,
+ scope_t& session_scope,
+ account_t * master = NULL,
+ const path * original_file = NULL,
+ bool strict = false);
+
+ bool has_xdata();
+ void clear_xdata();
+
+ bool valid() const;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & master;
+ ar & bucket;
+ ar & xacts;
+ ar & auto_xacts;
+ ar & period_xacts;
+ ar & sources;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+} // namespace ledger
+
+#endif // _JOURNAL_H
diff --git a/src/main.cc b/src/main.cc
new file mode 100644
index 00000000..0aec8886
--- /dev/null
+++ b/src/main.cc
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "global.h" // This is where the meat of main() is, which
+ // was moved there for the sake of clarity here
+#include "session.h"
+
+using namespace ledger;
+
+#ifdef HAVE_BOOST_PYTHON
+namespace ledger {
+ extern char * argv0;
+}
+#endif
+
+int main(int argc, char * argv[], char * envp[])
+{
+ int status = 1;
+
+#ifdef HAVE_BOOST_PYTHON
+ argv0 = argv[0];
+#endif
+
+ // The very first thing we do is handle some very special command-line
+ // options, since they affect how the environment is setup:
+ //
+ // --verify ; turns on memory tracing
+ // --verbose ; turns on logging
+ // --debug CATEGORY ; turns on debug logging
+ // --trace LEVEL ; turns on trace logging
+ handle_debug_options(argc, argv);
+#if defined(VERIFY_ON)
+ IF_VERIFY() initialize_memory_tracing();
+#endif
+
+ INFO("Ledger starting");
+
+ // Initialize global Boost/C++ environment
+ std::ios::sync_with_stdio(false);
+ filesystem::path::default_name_check(filesystem::portable_posix_name);
+
+ std::signal(SIGINT, sigint_handler);
+ std::signal(SIGPIPE, sigpipe_handler);
+
+#if defined(HAVE_GETTEXT)
+ ::textdomain("ledger");
+#endif
+
+ std::auto_ptr<global_scope_t> global_scope;
+
+ try {
+ // Create the session object, which maintains nearly all state relating to
+ // this invocation of Ledger; and register all known journal parsers.
+ global_scope.reset(new global_scope_t(envp));
+
+ global_scope->session().set_flush_on_next_data_file(true);
+
+ // Construct an STL-style argument list from the process command arguments
+ strings_list args;
+ for (int i = 1; i < argc; i++)
+ args.push_back(argv[i]);
+
+ // Look for options and a command verb in the command-line arguments
+ bind_scope_t bound_scope(*global_scope.get(), global_scope->report());
+
+ args = global_scope->read_command_arguments(bound_scope, args);
+
+ if (global_scope->HANDLED(script_)) {
+ // Ledger is being invoked as a script command interpreter
+ global_scope->session().read_journal_files();
+
+ status = 0;
+
+ ifstream in(global_scope->HANDLER(script_).str());
+ while (status == 0 && ! in.eof()) {
+ char line[1024];
+ in.getline(line, 1023);
+
+ char * p = skip_ws(line);
+ if (*p && *p != '#')
+ status = global_scope->execute_command_wrapper(split_arguments(p),
+ true);
+ }
+ }
+ else if (! args.empty()) {
+ // User has invoke a verb at the interactive command-line
+ status = global_scope->execute_command_wrapper(args, false);
+ }
+ else {
+ // Commence the REPL by displaying the current Ledger version
+ global_scope->show_version_info(std::cout);
+
+ global_scope->session().read_journal_files();
+
+ bool exit_loop = false;
+
+#ifdef HAVE_LIBEDIT
+
+ rl_readline_name = const_cast<char *>("Ledger");
+#if 0
+ // jww (2009-02-05): NYI
+ rl_attempted_completion_function = ledger_completion;
+#endif
+
+ while (char * p = readline(global_scope->prompt_string())) {
+ char * expansion = NULL;
+ int result;
+
+ result = history_expand(skip_ws(p), &expansion);
+
+ if (result < 0 || result == 2) {
+ if (expansion)
+ std::free(expansion);
+ std::free(p);
+ throw_(std::logic_error,
+ _("Failed to expand history reference '%1'") << p);
+ }
+ else if (expansion) {
+ add_history(expansion);
+ }
+
+#else // HAVE_LIBEDIT
+
+ while (! std::cin.eof()) {
+ std::cout << global_scope->prompt_string();
+ char line[1024];
+ std::cin.getline(line, 1023);
+
+ char * p = skip_ws(line);
+
+#endif // HAVE_LIBEDIT
+
+ check_for_signal();
+
+ if (*p && *p != '#') {
+ if (std::strncmp(p, "quit", 4) == 0)
+ exit_loop = true;
+ else
+ global_scope->execute_command_wrapper(split_arguments(p), true);
+ }
+
+#ifdef HAVE_LIBEDIT
+ if (expansion)
+ std::free(expansion);
+ std::free(p);
+#endif
+
+ if (exit_loop)
+ break;
+ }
+
+ status = 0; // report success
+ }
+ }
+ catch (const std::exception& err) {
+ if (global_scope.get())
+ global_scope->report_error(err);
+ else
+ std::cerr << "Exception during initialization: " << err.what()
+ << std::endl;
+ }
+ catch (int _status) {
+ status = _status; // used for a "quick" exit, and is used only
+ // if help text (such as --help) was displayed
+ }
+
+ // If memory verification is being performed (which can be very slow), clean
+ // up everything by closing the session and deleting the session object, and
+ // then shutting down the memory tracing subsystem. Otherwise, let it all
+ // leak because we're about to exit anyway.
+ IF_VERIFY() {
+ global_scope.reset();
+
+ INFO("Ledger ended (Boost/libstdc++ may still hold memory)");
+#if defined(VERIFY_ON)
+ shutdown_memory_tracing();
+#endif
+ } else {
+ INFO("Ledger ended");
+ }
+
+ // Return the final status to the operating system, either 1 for error or 0
+ // for a successful completion.
+ return status;
+}
+
+// main.cc ends here.
diff --git a/src/mask.cc b/src/mask.cc
new file mode 100644
index 00000000..c1e66ced
--- /dev/null
+++ b/src/mask.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "mask.h"
+
+namespace ledger {
+
+mask_t::mask_t(const string& pat) : expr()
+{
+ TRACE_CTOR(mask_t, "const string&");
+ *this = pat;
+}
+
+mask_t& mask_t::operator=(const string& pat)
+{
+#if defined(HAVE_BOOST_REGEX_UNICODE)
+ expr = boost::make_u32regex(pat.c_str(), boost::regex::perl | boost::regex::icase);
+#else
+ expr.assign(pat.c_str(), boost::regex::perl | boost::regex::icase);
+#endif
+ VERIFY(valid());
+ return *this;
+}
+
+} // namespace ledger
diff --git a/src/mask.h b/src/mask.h
new file mode 100644
index 00000000..4608898f
--- /dev/null
+++ b/src/mask.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup util
+ */
+
+/**
+ * @file mask.h
+ * @author John Wiegley
+ *
+ * @ingroup util
+ *
+ * @brief Regular expression masking.
+ */
+#ifndef _MASK_H
+#define _MASK_H
+
+#include "utils.h"
+#if defined(HAVE_BOOST_REGEX_UNICODE)
+#include "unistring.h"
+#endif
+
+namespace ledger {
+
+class mask_t
+{
+public:
+#if defined(HAVE_BOOST_REGEX_UNICODE)
+ boost::u32regex expr;
+#else
+ boost::regex expr;
+#endif
+
+ explicit mask_t(const string& pattern);
+
+ mask_t() : expr() {
+ TRACE_CTOR(mask_t, "");
+ }
+ mask_t(const mask_t& m) : expr(m.expr) {
+ TRACE_CTOR(mask_t, "copy");
+ }
+ ~mask_t() throw() {
+ TRACE_DTOR(mask_t);
+ }
+
+ mask_t& operator=(const string& other);
+
+ bool operator==(const mask_t& other) const {
+ return expr == other.expr;
+ }
+
+ bool match(const string& text) const {
+#if defined(HAVE_BOOST_REGEX_UNICODE)
+ DEBUG("mask.match",
+ "Matching: \"" << text << "\" =~ /" << str() << "/ = "
+ << (boost::u32regex_search(text, expr) ? "true" : "false"));
+ return boost::u32regex_search(text, expr);
+#else
+ DEBUG("mask.match",
+ "Matching: \"" << text << "\" =~ /" << str() << "/ = "
+ << (boost::regex_search(text, expr) ? "true" : "false"));
+ return boost::regex_search(text, expr);
+#endif
+ }
+
+ bool empty() const {
+ return expr.empty();
+ }
+
+ string str() const {
+ if (! empty()) {
+#if defined(HAVE_BOOST_REGEX_UNICODE)
+ assert(sizeof(boost::uint32_t) == sizeof(UChar32));
+ unistring ustr;
+ std::basic_string<UChar32> expr_str = expr.str();
+ std::copy(expr_str.begin(), expr_str.end(),
+ std::back_inserter(ustr.utf32chars));
+ return ustr.extract();
+#else
+ return expr.str();
+#endif
+ } else {
+ return empty_string;
+ }
+ }
+
+ bool valid() const {
+ if (expr.status() != 0) {
+ DEBUG("ledger.validate", "mask_t: expr.status() != 0");
+ return false;
+ }
+ return true;
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ string temp;
+ if (Archive::is_loading::value) {
+ ar & temp;
+ *this = temp;
+ } else {
+ temp = str();
+ ar & temp;
+ }
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+inline std::ostream& operator<<(std::ostream& out, const mask_t& mask) {
+ out << mask.str();
+ return out;
+}
+
+inline void to_xml(std::ostream& out, const mask_t& mask)
+{
+ push_xml x(out, "mask");
+ out << x.guard(mask.str());
+}
+
+} // namespace ledger
+
+#endif // _MASK_H
diff --git a/src/op.cc b/src/op.cc
new file mode 100644
index 00000000..f38fc86b
--- /dev/null
+++ b/src/op.cc
@@ -0,0 +1,732 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "op.h"
+#include "scope.h"
+#include "commodity.h"
+#include "pool.h"
+
+namespace ledger {
+
+expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
+{
+ if (is_ident()) {
+ DEBUG("expr.compile", "lookup: " << as_ident());
+
+ if (ptr_op_t def = scope.lookup(symbol_t::FUNCTION, as_ident())) {
+ // Identifier references are first looked up at the point of
+ // definition, and then at the point of every use if they could
+ // not be found there.
+ if (SHOW_DEBUG("expr.compile")) {
+ DEBUG("expr.compile", "Found definition:");
+ def->dump(*_log_stream, 0);
+ }
+ return copy(def);
+ }
+ else if (left()) {
+ return copy();
+ }
+ return this;
+ }
+
+ if (kind < TERMINALS)
+ return this;
+
+ if (kind == O_DEFINE) {
+ switch (left()->kind) {
+ case IDENT:
+ scope.define(symbol_t::FUNCTION, left()->as_ident(), right());
+ break;
+ case O_CALL:
+ if (left()->left()->is_ident())
+ scope.define(symbol_t::FUNCTION, left()->left()->as_ident(), this);
+ else
+ throw_(compile_error, _("Invalid function definition"));
+ break;
+ default:
+ throw_(compile_error, _("Invalid function definition"));
+ }
+ return wrap_value(value_t());
+ }
+
+ ptr_op_t lhs(left()->compile(scope, depth));
+ ptr_op_t rhs(kind > UNARY_OPERATORS && has_right() ?
+ (kind == O_LOOKUP ? right() :
+ right()->compile(scope, depth)) : NULL);
+
+ if (lhs == left() && (! rhs || rhs == right()))
+ return this;
+
+ ptr_op_t intermediate(copy(lhs, rhs));
+
+ // Reduce constants immediately if possible
+ if ((! lhs || lhs->is_value()) && (! rhs || rhs->is_value()))
+ return wrap_value(intermediate->calc(scope, NULL, depth));
+
+ return intermediate;
+}
+
+value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
+{
+#if defined(DEBUG_ON)
+ bool skip_debug = false;
+#endif
+ try {
+
+ value_t result;
+
+ switch (kind) {
+ case VALUE:
+ result = as_value();
+ break;
+
+ case IDENT: {
+ if (! left())
+ throw_(calc_error, _("Unknown identifier '%1'") << as_ident());
+
+ // Evaluating an identifier is the same as calling its definition
+ // directly, so we create an empty call_scope_t to reflect the scope for
+ // this implicit call.
+ call_scope_t call_args(scope);
+ result = left()->compile(call_args, depth + 1)
+ ->calc(call_args, locus, depth + 1);
+ break;
+ }
+
+ case FUNCTION: {
+ // Evaluating a FUNCTION is the same as calling it directly; this happens
+ // when certain functions-that-look-like-variables (such as "amount") are
+ // resolved.
+ call_scope_t call_args(scope);
+ result = as_function()(call_args);
+#if defined(DEBUG_ON)
+ skip_debug = true;
+#endif
+ break;
+ }
+
+ case O_DEFINE: {
+ call_scope_t& call_args(downcast<call_scope_t>(scope));
+ std::size_t args_count = call_args.size();
+ std::size_t args_index = 0;
+
+ assert(left()->kind == O_CALL);
+
+ for (ptr_op_t sym = left()->right();
+ sym;
+ sym = sym->has_right() ? sym->right() : NULL) {
+ ptr_op_t varname = sym;
+ if (sym->kind == O_CONS)
+ varname = sym->left();
+
+ if (! varname->is_ident())
+ throw_(calc_error, _("Invalid function definition"));
+ else if (args_index == args_count)
+ scope.define(symbol_t::FUNCTION, varname->as_ident(),
+ wrap_value(false));
+ else
+ scope.define(symbol_t::FUNCTION, varname->as_ident(),
+ wrap_value(call_args[args_index++]));
+ }
+
+ if (args_index < args_count)
+ throw_(calc_error,
+ _("Too many arguments in function call (saw %1)") << args_count);
+
+ result = right()->calc(scope, locus, depth + 1);
+ break;
+ }
+
+ case O_LOOKUP:
+ if (value_t obj = left()->calc(scope, locus, depth + 1)) {
+ if (obj.is_scope()) {
+ if (obj.as_scope() == NULL) {
+ throw_(calc_error, _("Left operand of . operator is NULL"));
+ } else {
+ scope_t& objscope(*obj.as_scope());
+ if (ptr_op_t member =
+ objscope.lookup(symbol_t::FUNCTION, right()->as_ident())) {
+ result = member->calc(objscope, NULL, depth + 1);
+ break;
+ }
+ }
+ }
+ }
+ if (right()->kind != IDENT)
+ throw_(calc_error,
+ _("Right operand of . operator must be an identifier"));
+ else
+ throw_(calc_error,
+ _("Failed to lookup member '%1'") << right()->as_ident());
+ break;
+
+ case O_CALL: {
+ call_scope_t call_args(scope);
+
+ if (has_right())
+ call_args.set_args(right()->calc(scope, locus, depth + 1));
+
+ ptr_op_t func = left();
+ const string& name(func->as_ident());
+
+ func = func->left();
+ if (! func)
+ throw_(calc_error, _("Calling unknown function '%1'") << name);
+
+ if (func->is_function())
+ result = func->as_function()(call_args);
+ else
+ result = func->calc(call_args, locus, depth + 1);
+ break;
+ }
+
+ case O_MATCH:
+ result = (right()->calc(scope, locus, depth + 1).as_mask()
+ .match(left()->calc(scope, locus, depth + 1).to_string()));
+ break;
+
+ case O_EQ:
+ result = (left()->calc(scope, locus, depth + 1) ==
+ right()->calc(scope, locus, depth + 1));
+ break;
+ case O_LT:
+ result = (left()->calc(scope, locus, depth + 1) <
+ right()->calc(scope, locus, depth + 1));
+ break;
+ case O_LTE:
+ result = (left()->calc(scope, locus, depth + 1) <=
+ right()->calc(scope, locus, depth + 1));
+ break;
+ case O_GT:
+ result = (left()->calc(scope, locus, depth + 1) >
+ right()->calc(scope, locus, depth + 1));
+ break;
+ case O_GTE:
+ result = (left()->calc(scope, locus, depth + 1) >=
+ right()->calc(scope, locus, depth + 1));
+ break;
+
+ case O_ADD:
+ result = (left()->calc(scope, locus, depth + 1) +
+ right()->calc(scope, locus, depth + 1));
+ break;
+ case O_SUB:
+ result = (left()->calc(scope, locus, depth + 1) -
+ right()->calc(scope, locus, depth + 1));
+ break;
+ case O_MUL:
+ result = (left()->calc(scope, locus, depth + 1) *
+ right()->calc(scope, locus, depth + 1));
+ break;
+ case O_DIV:
+ result = (left()->calc(scope, locus, depth + 1) /
+ right()->calc(scope, locus, depth + 1));
+ break;
+
+ case O_NEG:
+ result = left()->calc(scope, locus, depth + 1).negated();
+ break;
+
+ case O_NOT:
+ result = ! left()->calc(scope, locus, depth + 1);
+ break;
+
+ case O_AND:
+ if (left()->calc(scope, locus, depth + 1))
+ result = right()->calc(scope, locus, depth + 1);
+ else
+ result = false;
+ break;
+
+ case O_OR:
+ if (value_t temp = left()->calc(scope, locus, depth + 1))
+ result = temp;
+ else
+ result = right()->calc(scope, locus, depth + 1);
+ break;
+
+ case O_QUERY:
+ assert(right());
+ assert(right()->kind == O_COLON);
+
+ if (value_t temp = left()->calc(scope, locus, depth + 1))
+ result = right()->left()->calc(scope, locus, depth + 1);
+ else
+ result = right()->right()->calc(scope, locus, depth + 1);
+ break;
+
+ case O_COLON:
+ assert(! "We should never calculate an O_COLON operator");
+ break;
+
+ case O_CONS:
+ result = left()->calc(scope, locus, depth + 1);
+ DEBUG("op.cons", "car = " << result);
+
+ if (has_right()) {
+ value_t temp;
+ temp.push_back(result);
+
+ ptr_op_t next = right();
+ while (next) {
+ ptr_op_t value_op;
+ if (next->kind == O_CONS) {
+ value_op = next->left();
+ next = next->right();
+ } else {
+ value_op = next;
+ next = NULL;
+ }
+ temp.push_back(value_op->calc(scope, locus, depth + 1));
+ DEBUG("op.cons", "temp now = " << temp);
+ }
+ result = temp;
+ }
+ break;
+
+ case O_SEQ: {
+ symbol_scope_t seq_scope(scope);
+
+ // An O_SEQ is very similar to an O_CONS except that only the last result
+ // value in the series is kept. O_CONS builds up a list.
+ //
+ // Another feature of O_SEQ is that it pushes a new symbol scope onto the
+ // stack.
+ result = left()->calc(seq_scope, locus, depth + 1);
+
+ if (has_right()) {
+ ptr_op_t next = right();
+ while (next) {
+ ptr_op_t value_op;
+ if (next->kind == O_SEQ) {
+ value_op = next->left();
+ next = next->right();
+ } else {
+ value_op = next;
+ next = NULL;
+ }
+ result = value_op->calc(seq_scope, locus, depth + 1);
+ }
+ }
+ break;
+ }
+
+ case LAST:
+ default:
+ assert(false);
+ break;
+ }
+
+#if defined(DEBUG_ON)
+ if (! skip_debug && SHOW_DEBUG("expr.calc")) {
+ for (int i = 0; i < depth; i++)
+ ledger::_log_buffer << '.';
+ ledger::_log_buffer << op_context(this) << " => ";
+ result.dump(ledger::_log_buffer, true);
+ DEBUG("expr.calc", "");
+ }
+#endif
+
+ return result;
+
+ }
+ catch (const std::exception& err) {
+ if (locus && ! *locus)
+ *locus = this;
+ throw;
+ }
+}
+
+namespace {
+ bool print_cons(std::ostream& out, const expr_t::const_ptr_op_t op,
+ const expr_t::op_t::context_t& context)
+ {
+ bool found = false;
+
+ assert(op->left());
+ if (op->left()->print(out, context))
+ found = true;
+
+ if (op->has_right()) {
+ out << ", ";
+ if (op->right()->kind == expr_t::op_t::O_CONS)
+ found = print_cons(out, op->right(), context);
+ else if (op->right()->print(out, context))
+ found = true;
+ }
+ return found;
+ }
+
+ bool print_seq(std::ostream& out, const expr_t::const_ptr_op_t op,
+ const expr_t::op_t::context_t& context)
+ {
+ bool found = false;
+
+ assert(op->left());
+ if (op->left()->print(out, context))
+ found = true;
+
+ if (op->has_right()) {
+ out << "; ";
+
+ if (op->right()->kind == expr_t::op_t::O_CONS)
+ found = print_cons(out, op->right(), context);
+ else if (op->right()->print(out, context))
+ found = true;
+ }
+
+ return found;
+ }
+}
+
+bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
+{
+ bool found = false;
+
+ if (context.start_pos && this == context.op_to_find) {
+ *context.start_pos = out.tellp();
+ *context.start_pos -= 1;
+ found = true;
+ }
+
+ string symbol;
+
+ switch (kind) {
+ case VALUE:
+ as_value().dump(out, context.relaxed);
+ break;
+
+ case IDENT:
+ out << as_ident();
+ break;
+
+ case FUNCTION:
+ out << "<FUNCTION>";
+ break;
+
+ case O_NOT:
+ out << "!(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+ case O_NEG:
+ out << "-(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+
+ case O_ADD:
+ out << "(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " + ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+ case O_SUB:
+ out << "(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " - ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+ case O_MUL:
+ out << "(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " * ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+ case O_DIV:
+ out << "(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " / ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+
+ case O_EQ:
+ out << "(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " == ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+ case O_LT:
+ out << "(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " < ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+ case O_LTE:
+ out << "(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " <= ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+ case O_GT:
+ out << "(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " > ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+ case O_GTE:
+ out << "(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " >= ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+
+ case O_AND:
+ out << "(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " & ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+ case O_OR:
+ out << "(";
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " | ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ break;
+
+ case O_QUERY:
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " ? ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ break;
+
+ case O_COLON:
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " : ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ break;
+
+ case O_CONS:
+ found = print_cons(out, this, context);
+ break;
+
+ case O_SEQ:
+ out << "(";
+ found = print_seq(out, this, context);
+ out << ")";
+ break;
+
+ case O_DEFINE:
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " := ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ break;
+
+ case O_LOOKUP:
+ if (left() && left()->print(out, context))
+ found = true;
+ out << ".";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ break;
+
+ case O_CALL:
+ if (left() && left()->print(out, context))
+ found = true;
+ if (has_right()) {
+ if (right()->kind == O_SEQ) {
+ if (right()->print(out, context))
+ found = true;
+ } else {
+ out << "(";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ out << ")";
+ }
+ } else {
+ out << "()";
+ }
+ break;
+
+ case O_MATCH:
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " =~ ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ break;
+
+ case LAST:
+ default:
+ assert(false);
+ break;
+ }
+
+ if (! symbol.empty()) {
+ if (commodity_pool_t::current_pool->find(symbol))
+ out << '@';
+ out << symbol;
+ }
+
+ if (context.end_pos && this == context.op_to_find) {
+ *context.end_pos = out.tellp();
+ *context.end_pos -= 1;
+ }
+
+ return found;
+}
+
+void expr_t::op_t::dump(std::ostream& out, const int depth) const
+{
+ out.setf(std::ios::left);
+ out.width((sizeof(void *) * 2) + 2);
+ out << this;
+
+ for (int i = 0; i < depth; i++)
+ out << " ";
+
+ switch (kind) {
+ case VALUE:
+ out << "VALUE: ";
+ as_value().dump(out);
+ break;
+
+ case IDENT:
+ out << "IDENT: " << as_ident();
+ break;
+
+ case FUNCTION:
+ out << "FUNCTION";
+ break;
+
+ case O_DEFINE: out << "O_DEFINE"; break;
+ case O_LOOKUP: out << "O_LOOKUP"; break;
+ case O_CALL: out << "O_CALL"; break;
+ case O_MATCH: out << "O_MATCH"; break;
+
+ case O_NOT: out << "O_NOT"; break;
+ case O_NEG: out << "O_NEG"; break;
+
+ case O_ADD: out << "O_ADD"; break;
+ case O_SUB: out << "O_SUB"; break;
+ case O_MUL: out << "O_MUL"; break;
+ case O_DIV: out << "O_DIV"; break;
+
+ case O_EQ: out << "O_EQ"; break;
+ case O_LT: out << "O_LT"; break;
+ case O_LTE: out << "O_LTE"; break;
+ case O_GT: out << "O_GT"; break;
+ case O_GTE: out << "O_GTE"; break;
+
+ case O_AND: out << "O_AND"; break;
+ case O_OR: out << "O_OR"; break;
+
+ case O_QUERY: out << "O_QUERY"; break;
+ case O_COLON: out << "O_COLON"; break;
+
+ case O_CONS: out << "O_CONS"; break;
+ case O_SEQ: out << "O_SEQ"; break;
+
+ case LAST:
+ default:
+ assert(false);
+ break;
+ }
+
+ out << " (" << refc << ')' << std::endl;
+
+ // An identifier is a special non-terminal, in that its left() can
+ // hold the compiled definition of the identifier.
+ if (kind > TERMINALS || is_ident()) {
+ if (left()) {
+ left()->dump(out, depth + 1);
+ if (kind > UNARY_OPERATORS && has_right())
+ right()->dump(out, depth + 1);
+ }
+ else if (kind > UNARY_OPERATORS) {
+ assert(! has_right());
+ }
+ }
+}
+
+string op_context(const expr_t::ptr_op_t op,
+ const expr_t::ptr_op_t locus)
+{
+ ostream_pos_type start_pos, end_pos;
+ expr_t::op_t::context_t context(op, locus, &start_pos, &end_pos);
+ std::ostringstream buf;
+ buf << " ";
+ if (op->print(buf, context)) {
+ buf << "\n";
+ for (int i = 0; i <= end_pos; i++) {
+ if (i > start_pos)
+ buf << "^";
+ else
+ buf << " ";
+ }
+ }
+ return buf.str();
+}
+
+} // namespace ledger
diff --git a/src/op.h b/src/op.h
new file mode 100644
index 00000000..347eac1d
--- /dev/null
+++ b/src/op.h
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup expr
+ */
+
+/**
+ * @file op.h
+ * @author John Wiegley
+ *
+ * @ingroup expr
+ */
+#ifndef _OP_H
+#define _OP_H
+
+#include "expr.h"
+
+namespace ledger {
+
+class expr_t::op_t : public noncopyable
+{
+ friend class expr_t;
+ friend class expr_t::parser_t;
+
+public:
+ typedef expr_t::ptr_op_t ptr_op_t;
+
+private:
+ mutable short refc;
+ ptr_op_t left_;
+
+ variant<ptr_op_t, // used by all binary operators
+ value_t, // used by constant VALUE
+ string, // used by constant IDENT
+ expr_t::func_t // used by terminal FUNCTION
+ > data;
+
+public:
+ enum kind_t {
+ // Constants
+ VALUE,
+ IDENT,
+
+ CONSTANTS,
+
+ FUNCTION,
+
+ TERMINALS,
+
+ // Binary operators
+ O_NOT,
+ O_NEG,
+
+ UNARY_OPERATORS,
+
+ O_EQ,
+ O_LT,
+ O_LTE,
+ O_GT,
+ O_GTE,
+
+ O_AND,
+ O_OR,
+
+ O_ADD,
+ O_SUB,
+ O_MUL,
+ O_DIV,
+
+ O_QUERY,
+ O_COLON,
+
+ O_CONS,
+ O_SEQ,
+
+ O_DEFINE,
+ O_LOOKUP,
+ O_CALL,
+ O_MATCH,
+
+ BINARY_OPERATORS,
+
+ OPERATORS,
+
+ UNKNOWN,
+
+ LAST
+ };
+
+ kind_t kind;
+
+ explicit op_t() : refc(0), kind(UNKNOWN) {
+ TRACE_CTOR(op_t, "");
+ }
+ explicit op_t(const kind_t _kind) : refc(0), kind(_kind) {
+ TRACE_CTOR(op_t, "const kind_t");
+ }
+ ~op_t() {
+ TRACE_DTOR(op_t);
+ assert(refc == 0);
+ }
+
+ bool is_value() const {
+ if (kind == VALUE) {
+ assert(data.type() == typeid(value_t));
+ return true;
+ }
+ return false;
+ }
+ value_t& as_value_lval() {
+ assert(is_value());
+ value_t& val(boost::get<value_t>(data));
+ VERIFY(val.valid());
+ return val;
+ }
+ const value_t& as_value() const {
+ return const_cast<op_t *>(this)->as_value_lval();
+ }
+ void set_value(const value_t& val) {
+ VERIFY(val.valid());
+ data = val;
+ }
+
+ bool is_ident() const {
+ if (kind == IDENT) {
+ assert(data.type() == typeid(string));
+ return true;
+ }
+ return false;
+ }
+ string& as_ident_lval() {
+ assert(is_ident());
+ return boost::get<string>(data);
+ }
+ const string& as_ident() const {
+ return const_cast<op_t *>(this)->as_ident_lval();
+ }
+ void set_ident(const string& val) {
+ data = val;
+ }
+
+ bool is_function() const {
+ return kind == FUNCTION;
+ }
+ expr_t::func_t& as_function_lval() {
+ assert(kind == FUNCTION);
+ return boost::get<expr_t::func_t>(data);
+ }
+ const expr_t::func_t& as_function() const {
+ return const_cast<op_t *>(this)->as_function_lval();
+ }
+ void set_function(const expr_t::func_t& val) {
+ data = val;
+ }
+
+ ptr_op_t& left() {
+ assert(kind > TERMINALS || kind == IDENT);
+ return left_;
+ }
+ const ptr_op_t& left() const {
+ assert(kind > TERMINALS || kind == IDENT);
+ return left_;
+ }
+ void set_left(const ptr_op_t& expr) {
+ assert(kind > TERMINALS || kind == IDENT);
+ left_ = expr;
+ }
+
+ ptr_op_t& as_op_lval() {
+ assert(kind > TERMINALS || kind == IDENT);
+ return boost::get<ptr_op_t>(data);
+ }
+ const ptr_op_t& as_op() const {
+ return const_cast<op_t *>(this)->as_op_lval();
+ }
+
+ ptr_op_t& right() {
+ assert(kind > TERMINALS);
+ return as_op_lval();
+ }
+ const ptr_op_t& right() const {
+ assert(kind > TERMINALS);
+ return as_op();
+ }
+ void set_right(const ptr_op_t& expr) {
+ assert(kind > TERMINALS);
+ data = expr;
+ }
+ bool has_right() const {
+ if (kind < TERMINALS)
+ return false;
+ return as_op();
+ }
+
+private:
+ void acquire() const {
+ DEBUG("op.memory",
+ "Acquiring " << this << ", refc now " << refc + 1);
+ assert(refc >= 0);
+ refc++;
+ }
+ void release() const {
+ DEBUG("op.memory",
+ "Releasing " << this << ", refc now " << refc - 1);
+ assert(refc > 0);
+ if (--refc == 0)
+ checked_delete(this);
+ }
+
+ friend inline void intrusive_ptr_add_ref(const op_t * op) {
+ op->acquire();
+ }
+ friend inline void intrusive_ptr_release(const op_t * op) {
+ op->release();
+ }
+
+ ptr_op_t copy(ptr_op_t _left = NULL, ptr_op_t _right = NULL) const {
+ ptr_op_t node(new_node(kind, _left, _right));
+ if (kind < TERMINALS)
+ node->data = data;
+ return node;
+ }
+
+public:
+ static ptr_op_t new_node(kind_t _kind, ptr_op_t _left = NULL,
+ ptr_op_t _right = NULL);
+
+ ptr_op_t compile(scope_t& scope, const int depth = 0);
+ value_t calc(scope_t& scope, ptr_op_t * locus = NULL,
+ const int depth = 0);
+
+ struct context_t
+ {
+ ptr_op_t expr_op;
+ ptr_op_t op_to_find;
+ ostream_pos_type * start_pos;
+ ostream_pos_type * end_pos;
+ bool relaxed;
+
+ context_t(const ptr_op_t& _expr_op = NULL,
+ const ptr_op_t& _op_to_find = NULL,
+ ostream_pos_type * const _start_pos = NULL,
+ ostream_pos_type * const _end_pos = NULL,
+ const bool _relaxed = true)
+ : expr_op(_expr_op), op_to_find(_op_to_find),
+ start_pos(_start_pos), end_pos(_end_pos),
+ relaxed(_relaxed) {}
+ };
+
+ bool print(std::ostream& out, const context_t& context = context_t()) const;
+ void dump(std::ostream& out, const int depth) const;
+
+ static ptr_op_t wrap_value(const value_t& val);
+ static ptr_op_t wrap_functor(const expr_t::func_t& fobj);
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & refc;
+ ar & kind;
+ if (Archive::is_loading::value || ! left_ || left_->kind != FUNCTION) {
+ ar & left_;
+ } else {
+ ptr_op_t temp_op;
+ ar & temp_op;
+ }
+ if (Archive::is_loading::value || kind == VALUE || kind == IDENT ||
+ (kind > UNARY_OPERATORS &&
+ (! has_right() || ! right()->is_function()))) {
+ ar & data;
+ } else {
+ variant<ptr_op_t, value_t, string, expr_t::func_t> temp_data;
+ ar & temp_data;
+ }
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+inline expr_t::ptr_op_t
+expr_t::op_t::new_node(kind_t _kind, ptr_op_t _left, ptr_op_t _right)
+{
+ ptr_op_t node(new op_t(_kind));
+ if (_left) node->set_left(_left);
+ if (_right) node->set_right(_right);
+ return node;
+}
+
+inline expr_t::ptr_op_t expr_t::op_t::wrap_value(const value_t& val) {
+ ptr_op_t temp(new op_t(op_t::VALUE));
+ temp->set_value(val);
+ return temp;
+}
+
+inline expr_t::ptr_op_t
+expr_t::op_t::wrap_functor(const expr_t::func_t& fobj) {
+ ptr_op_t temp(new op_t(op_t::FUNCTION));
+ temp->set_function(fobj);
+ return temp;
+}
+
+#define MAKE_FUNCTOR(x) expr_t::op_t::wrap_functor(bind(&x, this, _1))
+#define WRAP_FUNCTOR(x) expr_t::op_t::wrap_functor(x)
+
+string op_context(const expr_t::ptr_op_t op,
+ const expr_t::ptr_op_t locus = NULL);
+
+} // namespace ledger
+
+#endif // _OP_H
diff --git a/src/option.cc b/src/option.cc
new file mode 100644
index 00000000..d2ec8808
--- /dev/null
+++ b/src/option.cc
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "option.h"
+
+namespace ledger {
+
+namespace {
+ typedef std::pair<expr_t::ptr_op_t, bool> op_bool_tuple;
+
+ op_bool_tuple find_option(scope_t& scope, const string& name)
+ {
+ char buf[128];
+ char * p = buf;
+ foreach (char ch, name) {
+ if (ch == '-')
+ *p++ = '_';
+ else
+ *p++ = ch;
+ }
+ *p++ = '_';
+ *p = '\0';
+
+ if (expr_t::ptr_op_t op = scope.lookup(symbol_t::OPTION, buf))
+ return op_bool_tuple(op, true);
+
+ *--p = '\0';
+
+ return op_bool_tuple(scope.lookup(symbol_t::OPTION, buf), false);
+ }
+
+ op_bool_tuple find_option(scope_t& scope, const char letter)
+ {
+ char buf[4];
+ buf[0] = letter;
+ buf[1] = '_';
+ buf[2] = '\0';
+
+ if (expr_t::ptr_op_t op = scope.lookup(symbol_t::OPTION, buf))
+ return op_bool_tuple(op, true);
+
+ buf[1] = '\0';
+
+ return op_bool_tuple(scope.lookup(symbol_t::OPTION, buf), false);
+ }
+
+ void process_option(const string& whence, const expr_t::func_t& opt,
+ scope_t& scope, const char * arg, const string& name)
+ {
+ try {
+ call_scope_t args(scope);
+
+ args.push_back(string_value(whence));
+ if (arg)
+ args.push_back(string_value(arg));
+
+ opt(args);
+ }
+ catch (const std::exception& err) {
+ if (name[0] == '-')
+ add_error_context(_("While parsing option '%1'") << name);
+
+ else
+ add_error_context(_("While parsing environent variable '%1'") << name);
+ throw;
+ }
+ }
+}
+
+bool process_option(const string& whence, const string& name, scope_t& scope,
+ const char * arg, const string& varname)
+{
+ op_bool_tuple opt(find_option(scope, name));
+ if (opt.first) {
+ process_option(whence, opt.first->as_function(), scope, arg, varname);
+ return true;
+ }
+ return false;
+}
+
+void process_environment(const char ** envp, const string& tag,
+ scope_t& scope)
+{
+ const char * tag_p = tag.c_str();
+ string::size_type tag_len = tag.length();
+
+ assert(tag_p);
+ assert(tag_len > 0);
+
+ for (const char ** p = envp; *p; p++) {
+ if (std::strlen(*p) >= tag_len && std::strncmp(*p, tag_p, tag_len) == 0) {
+ char buf[8192];
+ char * r = buf;
+ const char * q;
+ for (q = *p + tag_len;
+ *q && *q != '=' && r - buf < 8191;
+ q++)
+ if (*q == '_')
+ *r++ = '-';
+ else
+ *r++ = static_cast<char>(std::tolower(*q));
+ *r = '\0';
+
+ if (*q == '=') {
+ try {
+ string value = string(*p, q - *p);
+ if (! value.empty())
+ process_option(string("$") + buf, string(buf), scope, q + 1, value);
+ }
+ catch (const std::exception& err) {
+ add_error_context(_("While parsing environment variable option '%1':")
+ << *p);
+ throw;
+ }
+ }
+ }
+ }
+}
+
+namespace {
+ struct op_bool_char_tuple {
+ expr_t::ptr_op_t op;
+ bool truth;
+ char ch;
+
+ op_bool_char_tuple(expr_t::ptr_op_t _op, bool _truth, char _ch)
+ : op(_op), truth(_truth), ch(_ch) {}
+ };
+}
+
+strings_list process_arguments(strings_list args, scope_t& scope)
+{
+ bool anywhere = true;
+
+ strings_list remaining;
+
+ for (strings_list::iterator i = args.begin();
+ i != args.end();
+ i++) {
+ DEBUG("option.args", "Examining argument '" << *i << "'");
+
+ if (! anywhere || (*i)[0] != '-') {
+ DEBUG("option.args", " adding to list of real args");
+ remaining.push_back(*i);
+ continue;
+ }
+
+ // --long-option or -s
+ if ((*i)[1] == '-') {
+ if ((*i)[2] == '\0') {
+ DEBUG("option.args", " it's a --, ending options processing");
+ anywhere = false;
+ continue;
+ }
+
+ DEBUG("option.args", " it's an option string");
+
+ string opt_name;
+ const char * name = (*i).c_str() + 2;
+ const char * value = NULL;
+
+ if (const char * p = std::strchr(name, '=')) {
+ opt_name = string(name, p - name);
+ value = ++p;
+ DEBUG("option.args", " read option value from option: " << value);
+ } else {
+ opt_name = name;
+ }
+
+ op_bool_tuple opt(find_option(scope, opt_name));
+ if (! opt.first)
+ throw_(option_error, _("Illegal option --%1") << name);
+
+ if (opt.second && ! value && ++i != args.end() && value == NULL) {
+ value = (*i).c_str();
+ DEBUG("option.args", " read option value from arg: " << value);
+ if (value == NULL)
+ throw_(option_error, _("Missing option argument for --%1") << name);
+ }
+ process_option(string("--") + name,
+ opt.first->as_function(), scope, value,
+ string("--") + name);
+ }
+ else if ((*i)[1] == '\0') {
+ throw_(option_error, _("illegal option -%1") << (*i)[0]);
+ }
+ else {
+ DEBUG("option.args", " single-char option");
+
+ std::list<op_bool_char_tuple> option_queue;
+
+ int x = 1;
+ for (char c = (*i)[x]; c != '\0'; x++, c = (*i)[x]) {
+ op_bool_tuple opt(find_option(scope, c));
+ if (! opt.first)
+ throw_(option_error, _("Illegal option -%1") << c);
+
+ option_queue.push_back(op_bool_char_tuple(opt.first, opt.second, c));
+ }
+
+ foreach (op_bool_char_tuple& o, option_queue) {
+ const char * value = NULL;
+ if (o.truth && ++i != args.end()) {
+ value = (*i).c_str();
+ DEBUG("option.args", " read option value from arg: " << value);
+ if (value == NULL)
+ throw_(option_error,
+ _("Missing option argument for -%1") << o.ch);
+ }
+ process_option(string("-") + o.ch, o.op->as_function(), scope, value,
+ string("-") + o.ch);
+ }
+ }
+ }
+
+ return remaining;
+}
+
+} // namespace ledger
diff --git a/src/option.h b/src/option.h
new file mode 100644
index 00000000..b81c2ce7
--- /dev/null
+++ b/src/option.h
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup expr
+ */
+
+/**
+ * @file option.h
+ * @author John Wiegley
+ *
+ * @ingroup expr
+ */
+#ifndef _OPTION_H
+#define _OPTION_H
+
+#include "scope.h"
+
+namespace ledger {
+
+class call_scope_t;
+
+template <typename T>
+class option_t
+{
+protected:
+ const char * name;
+ string::size_type name_len;
+ const char ch;
+ bool handled;
+ optional<string> source;
+
+ option_t& operator=(const option_t&);
+
+public:
+ T * parent;
+ value_t value;
+ bool wants_arg;
+
+ option_t(const char * _name, const char _ch = '\0')
+ : name(_name), name_len(std::strlen(name)), ch(_ch),
+ handled(false), parent(NULL), value(),
+ wants_arg(name[name_len - 1] == '_') {
+ TRACE_CTOR(option_t, "const char *, const char");
+ DEBUG("option.names", "Option: " << name);
+ }
+ option_t(const option_t& other)
+ : name(other.name),
+ name_len(other.name_len),
+ ch(other.ch),
+ handled(other.handled),
+ parent(NULL),
+ value(other.value),
+ wants_arg(other.wants_arg)
+ {
+ TRACE_CTOR(option_t, "copy");
+ }
+
+ virtual ~option_t() {
+ TRACE_DTOR(option_t);
+ }
+
+ void report(std::ostream& out) const {
+ if (handled && source) {
+ if (wants_arg) {
+ out << desc() << " => ";
+ value.dump(out);
+ } else {
+ out << desc();
+ }
+ out << " <" << *source << ">" << std::endl;
+ }
+ }
+
+ string desc() const {
+ std::ostringstream out;
+ out << "--";
+ for (const char * p = name; *p; p++) {
+ if (*p == '_') {
+ if (*(p + 1))
+ out << '-';
+ } else {
+ out << *p;
+ }
+ }
+ if (ch)
+ out << " (-" << ch << ")";
+ return out.str();
+ }
+
+ operator bool() const {
+ return handled;
+ }
+
+ string& str() {
+ assert(handled);
+ if (! value)
+ throw_(std::runtime_error, _("No argument provided for %1") << desc());
+ return value.as_string_lval();
+ }
+
+ string str() const {
+ assert(handled);
+ if (! value)
+ throw_(std::runtime_error, _("No argument provided for %1") << desc());
+ return value.as_string();
+ }
+
+ void on_only(const optional<string>& whence) {
+ handled = true;
+ source = whence;
+ }
+ void on(const optional<string>& whence, const string& str) {
+ on_with(whence, string_value(str));
+ }
+ virtual void on_with(const optional<string>& whence,
+ const value_t& val) {
+ handled = true;
+ value = val;
+ source = whence;
+ }
+
+ void off() {
+ handled = false;
+ value = value_t();
+ source = none;
+ }
+
+ virtual void handler_thunk(call_scope_t&) {}
+
+ virtual void handler(call_scope_t& args) {
+ if (wants_arg) {
+ if (args.size() < 2)
+ throw_(std::runtime_error, _("No argument provided for %1") << desc());
+ else if (args.size() > 2)
+ throw_(std::runtime_error, _("To many arguments provided for %1") << desc());
+ else if (! args[0].is_string())
+ throw_(std::runtime_error, _("Context argument for %1 not a string") << desc());
+ on_with(args[0].as_string(), args[1]);
+ }
+ else if (args.size() < 1) {
+ throw_(std::runtime_error, _("No argument provided for %1") << desc());
+ }
+ else if (! args[0].is_string()) {
+ throw_(std::runtime_error, _("Context argument for %1 not a string") << desc());
+ }
+ else {
+ on_only(args[0].as_string());
+ }
+
+ handler_thunk(args);
+ }
+
+ virtual value_t handler_wrapper(call_scope_t& args) {
+ handler(args);
+ return true;
+ }
+
+ virtual value_t operator()(call_scope_t& args) {
+ if (! args.empty()) {
+ args.push_front(string_value("?expr"));
+ return handler_wrapper(args);
+ }
+ else if (wants_arg) {
+ if (handled)
+ return value;
+ else
+ return NULL_VALUE;
+ }
+ else {
+ return handled;
+ }
+ }
+};
+
+#define BEGIN(type, name) \
+ struct name ## _option_t : public option_t<type>
+
+#define CTOR(type, name) \
+ name ## _option_t() : option_t<type>(#name)
+#define DECL1(type, name, vartype, var, value) \
+ vartype var ; \
+ name ## _option_t() : option_t<type>(#name), var(value)
+
+#define DO() virtual void handler_thunk(call_scope_t&)
+#define DO_(var) virtual void handler_thunk(call_scope_t& var)
+
+#define END(name) name ## _handler
+
+#define COPY_OPT(name, other) name ## _handler(other.name ## _handler)
+
+#define MAKE_OPT_HANDLER(type, x) \
+ expr_t::op_t::wrap_functor(bind(&option_t<type>::handler_wrapper, x, _1))
+
+#define MAKE_OPT_FUNCTOR(type, x) \
+ expr_t::op_t::wrap_functor(bind(&option_t<type>::operator(), x, _1))
+
+inline bool is_eq(const char * p, const char * n) {
+ // Test whether p matches n, substituting - in p for _ in n.
+ for (; *p && *n; p++, n++) {
+ if (! (*p == '-' && *n == '_' ) && *p != *n)
+ return false;
+ }
+ // Ignore any trailing underscore
+ return *p == *n || (! *p && *n == '_' && ! *(n + 1));
+}
+
+#define OPT(name) \
+ if (is_eq(p, #name)) \
+ return ((name ## _handler).parent = this, &(name ## _handler))
+
+#define OPT_ALT(name, alt) \
+ if (is_eq(p, #name) || is_eq(p, #alt)) \
+ return ((name ## _handler).parent = this, &(name ## _handler))
+
+#define OPT_(name) \
+ if (! *(p + 1) || \
+ ((name ## _handler).wants_arg && \
+ *(p + 1) == '_' && ! *(p + 2)) || \
+ is_eq(p, #name)) \
+ return ((name ## _handler).parent = this, &(name ## _handler))
+
+#define OPT_CH(name) \
+ if (! *(p + 1) || \
+ ((name ## _handler).wants_arg && \
+ *(p + 1) == '_' && ! *(p + 2))) \
+ return ((name ## _handler).parent = this, &(name ## _handler))
+
+#define HANDLER(name) name ## _handler
+#define HANDLED(name) HANDLER(name)
+
+#define OPTION(type, name) \
+ BEGIN(type, name) \
+ { \
+ CTOR(type, name) {} \
+ } \
+ END(name)
+
+#define OPTION_(type, name, body) \
+ BEGIN(type, name) \
+ { \
+ CTOR(type, name) {} \
+ body \
+ } \
+ END(name)
+
+#define OPTION__(type, name, body) \
+ BEGIN(type, name) \
+ { \
+ body \
+ } \
+ END(name)
+
+bool process_option(const string& whence, const string& name, scope_t& scope,
+ const char * arg, const string& varname);
+
+void process_environment(const char ** envp, const string& tag,
+ scope_t& scope);
+
+strings_list process_arguments(strings_list args, scope_t& scope);
+
+DECLARE_EXCEPTION(option_error, std::runtime_error);
+
+} // namespace ledger
+
+#endif // _OPTION_H
diff --git a/src/output.cc b/src/output.cc
new file mode 100644
index 00000000..71ec6d88
--- /dev/null
+++ b/src/output.cc
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "output.h"
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "session.h"
+#include "report.h"
+
+namespace ledger {
+
+format_posts::format_posts(report_t& _report,
+ const string& format,
+ bool _print_raw,
+ const optional<string>& _prepend_format)
+ : report(_report), last_xact(NULL), last_post(NULL),
+ print_raw(_print_raw)
+{
+ TRACE_CTOR(format_posts, "report&, const string&, bool");
+
+ const char * f = format.c_str();
+
+ if (const char * p = std::strstr(f, "%/")) {
+ first_line_format.parse_format(string(f, 0, p - f));
+ const char * n = p + 2;
+ if (const char * p = std::strstr(n, "%/")) {
+ next_lines_format.parse_format(string(n, 0, p - n),
+ first_line_format);
+ between_format.parse_format(string(p + 2),
+ first_line_format);
+ } else {
+ next_lines_format.parse_format(string(n), first_line_format);
+ }
+ } else {
+ first_line_format.parse_format(format);
+ next_lines_format.parse_format(format);
+ }
+
+ if (_prepend_format)
+ prepend_format.parse_format(*_prepend_format);
+}
+
+void format_posts::flush()
+{
+ report.output_stream.flush();
+}
+
+void format_posts::operator()(post_t& post)
+{
+ std::ostream& out(report.output_stream);
+
+ if (print_raw) {
+ if (! post.has_xdata() ||
+ ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
+ if (last_xact != post.xact) {
+ if (last_xact) {
+ bind_scope_t xact_scope(report, *last_xact);
+ out << between_format(xact_scope);
+ }
+ print_item(out, *post.xact);
+ out << '\n';
+ last_xact = post.xact;
+ }
+ post.xdata().add_flags(POST_EXT_DISPLAYED);
+ last_post = &post;
+ }
+ }
+ else if (! post.has_xdata() ||
+ ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
+ bind_scope_t bound_scope(report, post);
+
+ if (prepend_format)
+ out << prepend_format(bound_scope);
+
+ if (last_xact != post.xact) {
+ if (last_xact) {
+ bind_scope_t xact_scope(report, *last_xact);
+ out << between_format(xact_scope);
+ }
+ out << first_line_format(bound_scope);
+ last_xact = post.xact;
+ }
+ else if (last_post && last_post->date() != post.date()) {
+ out << first_line_format(bound_scope);
+ }
+ else {
+ out << next_lines_format(bound_scope);
+ }
+
+ post.xdata().add_flags(POST_EXT_DISPLAYED);
+ last_post = &post;
+ }
+}
+
+format_accounts::format_accounts(report_t& _report,
+ const string& format,
+ const optional<string>& _prepend_format)
+ : report(_report), disp_pred()
+{
+ TRACE_CTOR(format_accounts, "report&, const string&");
+
+ const char * f = format.c_str();
+
+ if (const char * p = std::strstr(f, "%/")) {
+ account_line_format.parse_format(string(f, 0, p - f));
+ const char * n = p + 2;
+ if (const char * p = std::strstr(n, "%/")) {
+ total_line_format.parse_format(string(n, 0, p - n), account_line_format);
+ separator_format.parse_format(string(p + 2), account_line_format);
+ } else {
+ total_line_format.parse_format(n, account_line_format);
+ }
+ } else {
+ account_line_format.parse_format(format);
+ total_line_format.parse_format(format, account_line_format);
+ }
+
+ if (_prepend_format)
+ prepend_format.parse_format(*_prepend_format);
+}
+
+std::size_t format_accounts::post_account(account_t& account, const bool flat)
+{
+ if (account.xdata().has_flags(ACCOUNT_EXT_TO_DISPLAY) &&
+ ! account.xdata().has_flags(ACCOUNT_EXT_DISPLAYED)) {
+ if (! flat && account.parent &&
+ account.parent->xdata().has_flags(ACCOUNT_EXT_TO_DISPLAY) &&
+ ! account.parent->xdata().has_flags(ACCOUNT_EXT_DISPLAYED))
+ post_account(*account.parent, flat);
+
+ account.xdata().add_flags(ACCOUNT_EXT_DISPLAYED);
+
+ bind_scope_t bound_scope(report, account);
+
+ if (prepend_format)
+ static_cast<std::ostream&>(report.output_stream)
+ << prepend_format(bound_scope);
+
+ static_cast<std::ostream&>(report.output_stream)
+ << account_line_format(bound_scope);
+
+ return 1;
+ }
+ return 0;
+}
+
+std::pair<std::size_t, std::size_t>
+format_accounts::mark_accounts(account_t& account, const bool flat)
+{
+ std::size_t visited = 0;
+ std::size_t to_display = 0;
+
+ foreach (accounts_map::value_type& pair, account.accounts) {
+ std::pair<std::size_t, std::size_t> i = mark_accounts(*pair.second, flat);
+ visited += i.first;
+ to_display += i.second;
+ }
+
+#if defined(DEBUG_ON)
+ DEBUG("account.display", "Considering account: " << account.fullname());
+ if (account.has_xflags(ACCOUNT_EXT_VISITED))
+ DEBUG("account.display", " it was visited itself");
+ DEBUG("account.display", " it has " << visited << " visited children");
+ DEBUG("account.display",
+ " it has " << to_display << " children to display");
+#endif
+
+ if (account.parent &&
+ (account.has_xflags(ACCOUNT_EXT_VISITED) || (! flat && visited > 0))) {
+ bind_scope_t bound_scope(report, account);
+ if ((! flat && to_display > 1) ||
+ ((flat || to_display != 1 ||
+ account.has_xflags(ACCOUNT_EXT_VISITED)) &&
+ disp_pred(bound_scope))) {
+ account.xdata().add_flags(ACCOUNT_EXT_TO_DISPLAY);
+ DEBUG("account.display", "Marking account as TO_DISPLAY");
+ to_display = 1;
+ }
+ visited = 1;
+ }
+
+ return std::pair<std::size_t, std::size_t>(visited, to_display);
+}
+
+void format_accounts::flush()
+{
+ std::ostream& out(report.output_stream);
+
+ if (report.HANDLED(display_)) {
+ DEBUG("account.display",
+ "Account display predicate: " << report.HANDLER(display_).str());
+ disp_pred.parse(report.HANDLER(display_).str());
+ }
+
+ mark_accounts(*report.session.journal->master, report.HANDLED(flat));
+
+ std::size_t displayed = 0;
+
+ foreach (account_t * account, posted_accounts)
+ displayed += post_account(*account, report.HANDLED(flat));
+
+ if (displayed > 1 &&
+ ! report.HANDLED(no_total) && ! report.HANDLED(percent)) {
+ bind_scope_t bound_scope(report, *report.session.journal->master);
+ out << separator_format(bound_scope);
+
+ if (prepend_format)
+ static_cast<std::ostream&>(report.output_stream)
+ << prepend_format(bound_scope);
+
+ out << total_line_format(bound_scope);
+ }
+
+ out.flush();
+}
+
+void format_accounts::operator()(account_t& account)
+{
+ DEBUG("account.display", "Posting account: " << account.fullname());
+ posted_accounts.push_back(&account);
+}
+
+} // namespace ledger
diff --git a/src/output.h b/src/output.h
new file mode 100644
index 00000000..778a9335
--- /dev/null
+++ b/src/output.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup report
+ */
+
+/**
+ * @file output.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _OUTPUT_H
+#define _OUTPUT_H
+
+#include "chain.h"
+#include "predicate.h"
+#include "format.h"
+#include "account.h"
+
+namespace ledger {
+
+class xact_t;
+class post_t;
+class report_t;
+
+class format_posts : public item_handler<post_t>
+{
+protected:
+ report_t& report;
+ format_t first_line_format;
+ format_t next_lines_format;
+ format_t between_format;
+ format_t prepend_format;
+ xact_t * last_xact;
+ post_t * last_post;
+ bool print_raw;
+
+public:
+ format_posts(report_t& _report, const string& format,
+ bool _print_raw = false,
+ const optional<string>& _prepend_format = none);
+ virtual ~format_posts() {
+ TRACE_DTOR(format_posts);
+ }
+
+ virtual void flush();
+ virtual void operator()(post_t& post);
+};
+
+class format_accounts : public item_handler<account_t>
+{
+protected:
+ report_t& report;
+ format_t account_line_format;
+ format_t total_line_format;
+ format_t separator_format;
+ format_t prepend_format;
+ predicate_t disp_pred;
+
+ std::list<account_t *> posted_accounts;
+
+public:
+ format_accounts(report_t& _report, const string& _format,
+ const optional<string>& _prepend_format = none);
+ virtual ~format_accounts() {
+ TRACE_DTOR(format_accounts);
+ }
+
+ std::pair<std::size_t, std::size_t>
+ mark_accounts(account_t& account, const bool flat);
+
+ virtual std::size_t post_account(account_t& account, const bool flat);
+ virtual void flush();
+
+ virtual void operator()(account_t& account);
+};
+
+} // namespace ledger
+
+#endif // _OUTPUT_H
diff --git a/src/parser.cc b/src/parser.cc
new file mode 100644
index 00000000..ef778411
--- /dev/null
+++ b/src/parser.cc
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "parser.h"
+
+namespace ledger {
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_value_term(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node;
+
+ token_t& tok = next_token(in, tflags);
+
+ switch (tok.kind) {
+ case token_t::VALUE:
+ node = new op_t(op_t::VALUE);
+ node->set_value(tok.value);
+ break;
+
+ case token_t::IDENT: {
+ string ident = tok.value.as_string();
+
+ node = new op_t(op_t::IDENT);
+ node->set_ident(ident);
+
+ // An identifier followed by ( represents a function call
+ tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+ if (tok.kind == token_t::LPAREN) {
+ ptr_op_t call_node(new op_t(op_t::O_CALL));
+ call_node->set_left(node);
+ node = call_node;
+
+ push_token(tok); // let the parser see it again
+ node->set_right(parse_value_expr(in, tflags.plus_flags(PARSE_SINGLE)));
+
+ if (node->has_right() && node->right()->kind == op_t::O_CONS)
+ node->set_right(node->right()->left());
+ } else {
+ push_token(tok);
+ }
+ break;
+ }
+
+ case token_t::LPAREN:
+ node = parse_value_expr(in, tflags.plus_flags(PARSE_PARTIAL)
+ .minus_flags(PARSE_SINGLE));
+ tok = next_token(in, tflags);
+ if (tok.kind != token_t::RPAREN)
+ tok.expected(')');
+
+ if (node->kind == op_t::O_CONS) {
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_SEQ);
+ node->set_left(prev);
+ }
+ break;
+
+ default:
+ push_token(tok);
+ break;
+ }
+
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_dot_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node(parse_value_term(in, tflags));
+
+ if (node && ! tflags.has_flags(PARSE_SINGLE)) {
+ while (true) {
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+ if (tok.kind == token_t::DOT) {
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_LOOKUP);
+ node->set_left(prev);
+ node->set_right(parse_value_term(in, tflags));
+ if (! node->right())
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol);
+ } else {
+ push_token(tok);
+ break;
+ }
+ }
+ }
+
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_unary_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node;
+
+ token_t& tok = next_token(in, tflags);
+
+ switch (tok.kind) {
+ case token_t::EXCLAM: {
+ ptr_op_t term(parse_dot_expr(in, tflags));
+ if (! term)
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol);
+
+ // A very quick optimization
+ if (term->kind == op_t::VALUE) {
+ term->as_value_lval().in_place_not();
+ node = term;
+ } else {
+ node = new op_t(op_t::O_NOT);
+ node->set_left(term);
+ }
+ break;
+ }
+
+ case token_t::MINUS: {
+ ptr_op_t term(parse_dot_expr(in, tflags));
+ if (! term)
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol);
+
+ // A very quick optimization
+ if (term->kind == op_t::VALUE) {
+ term->as_value_lval().in_place_negate();
+ node = term;
+ } else {
+ node = new op_t(op_t::O_NEG);
+ node->set_left(term);
+ }
+ break;
+ }
+
+ default:
+ push_token(tok);
+ node = parse_dot_expr(in, tflags);
+ break;
+ }
+
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_mul_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node(parse_unary_expr(in, tflags));
+
+ if (node && ! tflags.has_flags(PARSE_SINGLE)) {
+ while (true) {
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+
+ if (tok.kind == token_t::STAR || tok.kind == token_t::SLASH ||
+ tok.kind == token_t::KW_DIV) {
+ ptr_op_t prev(node);
+ node = new op_t(tok.kind == token_t::STAR ?
+ op_t::O_MUL : op_t::O_DIV);
+ node->set_left(prev);
+ node->set_right(parse_unary_expr(in, tflags));
+ if (! node->right())
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol);
+ } else {
+ push_token(tok);
+ break;
+ }
+ }
+ }
+
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_add_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node(parse_mul_expr(in, tflags));
+
+ if (node && ! tflags.has_flags(PARSE_SINGLE)) {
+ while (true) {
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+
+ if (tok.kind == token_t::PLUS ||
+ tok.kind == token_t::MINUS) {
+ ptr_op_t prev(node);
+ node = new op_t(tok.kind == token_t::PLUS ?
+ op_t::O_ADD : op_t::O_SUB);
+ node->set_left(prev);
+ node->set_right(parse_mul_expr(in, tflags));
+ if (! node->right())
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol);
+ } else {
+ push_token(tok);
+ break;
+ }
+ }
+ }
+
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_logic_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node(parse_add_expr(in, tflags));
+
+ if (node && ! tflags.has_flags(PARSE_SINGLE)) {
+ while (true) {
+ op_t::kind_t kind = op_t::LAST;
+ parse_flags_t _flags = tflags;
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+ bool negate = false;
+
+ switch (tok.kind) {
+ case token_t::DEFINE:
+ kind = op_t::O_DEFINE;
+ break;
+ case token_t::EQUAL:
+ if (tflags.has_flags(PARSE_NO_ASSIGN))
+ tok.rewind(in);
+ else
+ kind = op_t::O_EQ;
+ break;
+ case token_t::NEQUAL:
+ kind = op_t::O_EQ;
+ negate = true;
+ break;
+ case token_t::MATCH:
+ kind = op_t::O_MATCH;
+ break;
+ case token_t::NMATCH:
+ kind = op_t::O_MATCH;
+ negate = true;
+ break;
+ case token_t::LESS:
+ kind = op_t::O_LT;
+ break;
+ case token_t::LESSEQ:
+ kind = op_t::O_LTE;
+ break;
+ case token_t::GREATER:
+ kind = op_t::O_GT;
+ break;
+ case token_t::GREATEREQ:
+ kind = op_t::O_GTE;
+ break;
+ default:
+ push_token(tok);
+ goto exit_loop;
+ }
+
+ if (kind != op_t::LAST) {
+ ptr_op_t prev(node);
+ node = new op_t(kind);
+ node->set_left(prev);
+ node->set_right(parse_add_expr(in, _flags));
+
+ if (! node->right())
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol);
+
+ if (negate) {
+ prev = node;
+ node = new op_t(op_t::O_NOT);
+ node->set_left(prev);
+ }
+ }
+ }
+ }
+
+ exit_loop:
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_and_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node(parse_logic_expr(in, tflags));
+
+ if (node && ! tflags.has_flags(PARSE_SINGLE)) {
+ while (true) {
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+
+ if (tok.kind == token_t::KW_AND) {
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_AND);
+ node->set_left(prev);
+ node->set_right(parse_logic_expr(in, tflags));
+ if (! node->right())
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol);
+ } else {
+ push_token(tok);
+ break;
+ }
+ }
+ }
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_or_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node(parse_and_expr(in, tflags));
+
+ if (node && ! tflags.has_flags(PARSE_SINGLE)) {
+ while (true) {
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+
+ if (tok.kind == token_t::KW_OR) {
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_OR);
+ node->set_left(prev);
+ node->set_right(parse_and_expr(in, tflags));
+ if (! node->right())
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol);
+ } else {
+ push_token(tok);
+ break;
+ }
+ }
+ }
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_querycolon_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node(parse_or_expr(in, tflags));
+
+ if (node && ! tflags.has_flags(PARSE_SINGLE)) {
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+
+ if (tok.kind == token_t::QUERY) {
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_QUERY);
+ node->set_left(prev);
+ node->set_right(parse_or_expr(in, tflags));
+ if (! node->right())
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol);
+
+ token_t& next_tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+ if (next_tok.kind != token_t::COLON)
+ next_tok.expected(':');
+
+ prev = node->right();
+ ptr_op_t subnode = new op_t(op_t::O_COLON);
+ subnode->set_left(prev);
+ subnode->set_right(parse_or_expr(in, tflags));
+ if (! subnode->right())
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol);
+
+ node->set_right(subnode);
+ }
+ else if (tok.kind == token_t::KW_IF) {
+ ptr_op_t if_op(parse_or_expr(in, tflags));
+ if (! if_op)
+ throw_(parse_error, _("'if' keyword not followed by argument"));
+
+ tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+ if (tok.kind == token_t::KW_ELSE) {
+ ptr_op_t else_op(parse_or_expr(in, tflags));
+ if (! else_op)
+ throw_(parse_error, _("'else' keyword not followed by argument"));
+
+ ptr_op_t subnode = new op_t(op_t::O_COLON);
+ subnode->set_left(node);
+ subnode->set_right(else_op);
+
+ node = new op_t(op_t::O_QUERY);
+ node->set_left(if_op);
+ node->set_right(subnode);
+ } else {
+ ptr_op_t null_node = new op_t(op_t::VALUE);
+ null_node->set_value(NULL_VALUE);
+
+ ptr_op_t subnode = new op_t(op_t::O_COLON);
+ subnode->set_left(node);
+ subnode->set_right(null_node);
+
+ node = new op_t(op_t::O_QUERY);
+ node->set_left(if_op);
+ node->set_right(subnode);
+
+ push_token(tok);
+ }
+ }
+ else {
+ push_token(tok);
+ }
+ }
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_value_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node(parse_querycolon_expr(in, tflags));
+
+ if (node && ! tflags.has_flags(PARSE_SINGLE)) {
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+
+ if (tok.kind == token_t::COMMA || tok.kind == token_t::SEMI) {
+ bool comma_op = tok.kind == token_t::COMMA;
+
+ ptr_op_t prev(node);
+ node = new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ);
+ node->set_left(prev);
+ node->set_right(parse_value_expr(in, tflags));
+ if (! node->right())
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol);
+
+ tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+ }
+
+ if (tok.kind != token_t::TOK_EOF) {
+ if (tflags.has_flags(PARSE_PARTIAL))
+ push_token(tok);
+ else
+ tok.unexpected();
+ }
+ }
+ else if (! tflags.has_flags(PARSE_PARTIAL) &&
+ ! tflags.has_flags(PARSE_SINGLE)) {
+ throw_(parse_error, _("Failed to parse value expression"));
+ }
+
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse(std::istream& in,
+ const parse_flags_t& flags,
+ const optional<string>& original_string)
+{
+ try {
+ ptr_op_t top_node = parse_value_expr(in, flags);
+
+ if (use_lookahead) {
+ use_lookahead = false;
+ lookahead.rewind(in);
+ }
+ lookahead.clear();
+
+ return top_node;
+ }
+ catch (const std::exception& err) {
+ if (original_string) {
+ add_error_context(_("While parsing value expression:"));
+
+ std::streamoff end_pos = 0;
+ if (in.good())
+ end_pos = in.tellg();
+ std::streamoff pos = end_pos;
+
+ if (pos > 0)
+ pos -= lookahead.length;
+
+ DEBUG("parser.error", "original_string = '" << *original_string << "'");
+ DEBUG("parser.error", " pos = " << pos);
+ DEBUG("parser.error", " end_pos = " << end_pos);
+ DEBUG("parser.error", " token kind = " << int(lookahead.kind));
+ DEBUG("parser.error", " token length = " << lookahead.length);
+
+ add_error_context(line_context(*original_string,
+ static_cast<string::size_type>(pos),
+ static_cast<string::size_type>(end_pos)));
+ }
+ throw;
+ }
+}
+
+} // namespace ledger
diff --git a/src/parser.h b/src/parser.h
new file mode 100644
index 00000000..7a69fe08
--- /dev/null
+++ b/src/parser.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup expr
+ */
+
+/**
+ * @file parser.h
+ * @author John Wiegley
+ *
+ * @ingroup expr
+ */
+#ifndef _PARSER_H
+#define _PARSER_H
+
+#include "token.h"
+#include "op.h"
+
+namespace ledger {
+
+class expr_t::parser_t : public noncopyable
+{
+ mutable token_t lookahead;
+ mutable bool use_lookahead;
+
+ token_t& next_token(std::istream& in, const parse_flags_t& tflags) const {
+ if (use_lookahead)
+ use_lookahead = false;
+ else
+ lookahead.next(in, tflags);
+ return lookahead;
+ }
+
+ void push_token(const token_t& tok) const {
+ assert(&tok == &lookahead);
+ use_lookahead = true;
+ }
+ void push_token() const {
+ use_lookahead = true;
+ }
+
+ ptr_op_t parse_value_term(std::istream& in,
+ const parse_flags_t& flags) const;
+ ptr_op_t parse_dot_expr(std::istream& in,
+ const parse_flags_t& flags) const;
+ ptr_op_t parse_unary_expr(std::istream& in,
+ const parse_flags_t& flags) const;
+ ptr_op_t parse_mul_expr(std::istream& in,
+ const parse_flags_t& flags) const;
+ ptr_op_t parse_add_expr(std::istream& in,
+ const parse_flags_t& flags) const;
+ ptr_op_t parse_logic_expr(std::istream& in,
+ const parse_flags_t& flags) const;
+ ptr_op_t parse_and_expr(std::istream& in,
+ const parse_flags_t& flags) const;
+ ptr_op_t parse_or_expr(std::istream& in,
+ const parse_flags_t& flags) const;
+ ptr_op_t parse_querycolon_expr(std::istream& in,
+ const parse_flags_t& flags) const;
+ ptr_op_t parse_value_expr(std::istream& in,
+ const parse_flags_t& flags) const;
+
+public:
+ parser_t() : use_lookahead(false) {
+ TRACE_CTOR(parser_t, "");
+ }
+ ~parser_t() throw() {
+ TRACE_DTOR(parser_t);
+ }
+
+ ptr_op_t parse(std::istream& in,
+ const parse_flags_t& flags = PARSE_DEFAULT,
+ const optional<string>& original_string = NULL);
+};
+
+} // namespace ledger
+
+#endif // _PARSER_H
diff --git a/src/pool.cc b/src/pool.cc
new file mode 100644
index 00000000..70f4eed6
--- /dev/null
+++ b/src/pool.cc
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "amount.h"
+#include "commodity.h"
+#include "annotate.h"
+#include "pool.h"
+#include "quotes.h"
+
+namespace ledger {
+
+shared_ptr<commodity_pool_t> commodity_pool_t::current_pool;
+
+commodity_pool_t::commodity_pool_t()
+ : default_commodity(NULL), keep_base(false),
+ quote_leeway(86400), get_quotes(false),
+ get_commodity_quote(commodity_quote_from_script)
+{
+ TRACE_CTOR(commodity_pool_t, "");
+ null_commodity = create("");
+ null_commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
+}
+
+commodity_t * commodity_pool_t::create(const string& symbol)
+{
+ shared_ptr<commodity_t::base_t>
+ base_commodity(new commodity_t::base_t(symbol));
+ std::auto_ptr<commodity_t> commodity(new commodity_t(this, base_commodity));
+
+ DEBUG("amounts.commodities", "Creating base commodity " << symbol);
+
+ // Create the "qualified symbol" version of this commodity's symbol
+ if (commodity_t::symbol_needs_quotes(symbol)) {
+ commodity->qualified_symbol = "\"";
+ *commodity->qualified_symbol += symbol;
+ *commodity->qualified_symbol += "\"";
+ }
+
+ DEBUG("amounts.commodities",
+ "Creating commodity '" << commodity->symbol() << "'");
+
+ std::pair<commodities_map::iterator, bool> result
+ = commodities.insert(commodities_map::value_type(commodity->mapping_key(),
+ commodity.get()));
+ assert(result.second);
+
+ return commodity.release();
+}
+
+commodity_t * commodity_pool_t::find_or_create(const string& symbol)
+{
+ DEBUG("amounts.commodities", "Find-or-create commodity " << symbol);
+
+ commodity_t * commodity = find(symbol);
+ if (commodity)
+ return commodity;
+ return create(symbol);
+}
+
+commodity_t * commodity_pool_t::find(const string& symbol)
+{
+ DEBUG("amounts.commodities", "Find commodity " << symbol);
+
+ commodities_map::const_iterator i = commodities.find(symbol);
+ if (i != commodities.end())
+ return (*i).second;
+ return NULL;
+}
+
+commodity_t *
+commodity_pool_t::create(const string& symbol, const annotation_t& details)
+{
+ commodity_t * new_comm = create(symbol);
+ if (! new_comm)
+ return NULL;
+
+ if (details)
+ return find_or_create(*new_comm, details);
+ else
+ return new_comm;
+}
+
+string commodity_pool_t::make_qualified_name(const commodity_t& comm,
+ const annotation_t& details)
+{
+ assert(details);
+
+ if (details.price && details.price->sign() < 0)
+ throw_(amount_error, _("A commodity's price may not be negative"));
+
+ std::ostringstream name;
+ comm.print(name);
+ details.print(name, comm.pool().keep_base);
+
+ DEBUG("amounts.commodities", "make_qualified_name for "
+ << *comm.qualified_symbol << std::endl << details);
+ DEBUG("amounts.commodities", "qualified_name is " << name.str());
+
+ return name.str();
+}
+
+commodity_t *
+commodity_pool_t::find(const string& symbol, const annotation_t& details)
+{
+ commodity_t * comm = find(symbol);
+ if (! comm)
+ return NULL;
+
+ if (details) {
+ string name = make_qualified_name(*comm, details);
+
+ if (commodity_t * ann_comm = find(name)) {
+ assert(ann_comm->annotated && as_annotated_commodity(*ann_comm).details);
+ return ann_comm;
+ }
+ return NULL;
+ } else {
+ return comm;
+ }
+}
+
+commodity_t *
+commodity_pool_t::find_or_create(const string& symbol,
+ const annotation_t& details)
+{
+ commodity_t * comm = find(symbol);
+ if (! comm)
+ return NULL;
+
+ if (details)
+ return find_or_create(*comm, details);
+ else
+ return comm;
+}
+
+commodity_t *
+commodity_pool_t::create(commodity_t& comm,
+ const annotation_t& details,
+ const string& mapping_key)
+{
+ assert(comm);
+ assert(details);
+ assert(! mapping_key.empty());
+
+ std::auto_ptr<commodity_t> commodity
+ (new annotated_commodity_t(&comm, details));
+
+ commodity->qualified_symbol = comm.symbol();
+ assert(! commodity->qualified_symbol->empty());
+
+ DEBUG("amounts.commodities", "Creating annotated commodity "
+ << "symbol " << commodity->symbol()
+ << " key " << mapping_key << std::endl << details);
+
+ // Add the fully annotated name to the map, so that this symbol may
+ // quickly be found again.
+ commodity->mapping_key_ = mapping_key;
+
+ std::pair<commodities_map::iterator, bool> result
+ = commodities.insert(commodities_map::value_type(mapping_key,
+ commodity.get()));
+ assert(result.second);
+
+ return commodity.release();
+}
+
+commodity_t * commodity_pool_t::find_or_create(commodity_t& comm,
+ const annotation_t& details)
+{
+ assert(comm);
+ assert(details);
+
+ string name = make_qualified_name(comm, details);
+ assert(! name.empty());
+
+ if (commodity_t * ann_comm = find(name)) {
+ assert(ann_comm->annotated && as_annotated_commodity(*ann_comm).details);
+ return ann_comm;
+ }
+ return create(comm, details, name);
+}
+
+void commodity_pool_t::exchange(commodity_t& commodity,
+ const amount_t& per_unit_cost,
+ const datetime_t& moment)
+{
+ DEBUG("commodity.prices.add", "exchanging commodity " << commodity
+ << " at per unit cost " << per_unit_cost << " on " << moment);
+
+ commodity_t& base_commodity
+ (commodity.annotated ?
+ as_annotated_commodity(commodity).referent() : commodity);
+
+ base_commodity.add_price(moment, per_unit_cost);
+}
+
+cost_breakdown_t
+commodity_pool_t::exchange(const amount_t& amount,
+ const amount_t& cost,
+ const bool is_per_unit,
+ const optional<datetime_t>& moment,
+ const optional<string>& tag)
+{
+ DEBUG("commodity.prices.add", "exchange: " << amount << " for " << cost);
+ DEBUG("commodity.prices.add", "exchange: is-per-unit = " << is_per_unit);
+#if defined(DEBUG_ON)
+ if (moment)
+ DEBUG("commodity.prices.add", "exchange: moment = " << *moment);
+ if (tag)
+ DEBUG("commodity.prices.add", "exchange: tag = " << *tag);
+#endif
+
+ commodity_t& commodity(amount.commodity());
+
+ annotation_t * current_annotation = NULL;
+ if (commodity.annotated)
+ current_annotation = &as_annotated_commodity(commodity).details;
+
+ amount_t per_unit_cost =
+ (is_per_unit || amount.is_realzero() ? cost : cost / amount).abs();
+
+ DEBUG("commodity.prices.add", "exchange: per-unit-cost = " << per_unit_cost);
+
+ if (! per_unit_cost.is_realzero())
+ exchange(commodity, per_unit_cost, moment ? *moment : CURRENT_TIME());
+
+ cost_breakdown_t breakdown;
+ breakdown.final_cost = ! is_per_unit ? cost : cost * amount;
+
+ DEBUG("commodity.prices.add",
+ "exchange: final-cost = " << breakdown.final_cost);
+
+ if (current_annotation && current_annotation->price)
+ breakdown.basis_cost
+ = (*current_annotation->price * amount).unrounded();
+ else
+ breakdown.basis_cost = breakdown.final_cost;
+
+ DEBUG("commodity.prices.add",
+ "exchange: basis-cost = " << breakdown.basis_cost);
+
+ annotation_t annotation(per_unit_cost, moment ?
+ moment->date() : optional<date_t>(), tag);
+
+ annotation.add_flags(ANNOTATION_PRICE_CALCULATED);
+ if (moment)
+ annotation.add_flags(ANNOTATION_DATE_CALCULATED);
+ if (tag)
+ annotation.add_flags(ANNOTATION_TAG_CALCULATED);
+
+ breakdown.amount = amount_t(amount, annotation);
+
+ DEBUG("commodity.prices.add",
+ "exchange: amount = " << breakdown.amount);
+
+ return breakdown;
+}
+
+optional<std::pair<commodity_t *, price_point_t> >
+commodity_pool_t::parse_price_directive(char * line, bool do_not_add_price)
+{
+ char * date_field_ptr = line;
+ char * time_field_ptr = next_element(date_field_ptr);
+ if (! time_field_ptr) return none;
+ string date_field = date_field_ptr;
+
+ char * symbol_and_price;
+ datetime_t datetime;
+ string symbol;
+
+ if (std::isdigit(time_field_ptr[0])) {
+ symbol_and_price = next_element(time_field_ptr);
+ if (! symbol_and_price) return none;
+
+ datetime = parse_datetime(date_field + " " + time_field_ptr);
+ }
+ else if (std::isdigit(date_field_ptr[0])) {
+ symbol_and_price = time_field_ptr;
+ datetime = datetime_t(parse_date(date_field));
+ }
+ else {
+ symbol = date_field_ptr;
+ symbol_and_price = time_field_ptr;
+ datetime = CURRENT_TIME();
+ }
+
+ if (symbol.empty())
+ commodity_t::parse_symbol(symbol_and_price, symbol);
+
+ price_point_t point;
+ point.when = datetime;
+ point.price.parse(symbol_and_price, PARSE_NO_MIGRATE);
+ VERIFY(point.price.valid());
+
+ DEBUG("commodity.download", "Looking up symbol: " << symbol);
+ if (commodity_t * commodity = find_or_create(symbol)) {
+ DEBUG("commodity.download", "Adding price for " << symbol << ": "
+ << point.when << " " << point.price);
+ if (! do_not_add_price)
+ commodity->add_price(point.when, point.price, true);
+ commodity->add_flags(COMMODITY_KNOWN);
+ return std::pair<commodity_t *, price_point_t>(commodity, point);
+ }
+
+ return none;
+}
+
+commodity_t *
+commodity_pool_t::parse_price_expression(const std::string& str,
+ const bool add_prices,
+ const optional<datetime_t>& moment)
+{
+ scoped_array<char> buf(new char[str.length() + 1]);
+
+ std::strcpy(buf.get(), str.c_str());
+
+ char * price = std::strchr(buf.get(), '=');
+ if (price)
+ *price++ = '\0';
+
+ if (commodity_t * commodity = find_or_create(trim_ws(buf.get()))) {
+ if (price && add_prices) {
+ for (char * p = std::strtok(price, ";");
+ p;
+ p = std::strtok(NULL, ";")) {
+ commodity->add_price(moment ? *moment : CURRENT_TIME(), amount_t(p));
+ }
+ }
+ return commodity;
+ }
+ return NULL;
+}
+
+} // namespace ledger
diff --git a/src/pool.h b/src/pool.h
new file mode 100644
index 00000000..995ab23c
--- /dev/null
+++ b/src/pool.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup math
+ */
+
+/**
+ * @file pool.h
+ * @author John Wiegley
+ *
+ * @ingroup math
+ *
+ * @brief Types for managing commodity pools
+ *
+ * Long.
+ */
+#ifndef _POOL_H
+#define _POOL_H
+
+namespace ledger {
+
+struct cost_breakdown_t
+{
+ amount_t amount;
+ amount_t final_cost;
+ amount_t basis_cost;
+};
+
+class commodity_pool_t : public noncopyable
+{
+public:
+ /**
+ * The commodities collection in commodity_pool_t maintains pointers to all
+ * the commodities which have ever been created by the user, whether
+ * explicitly by calling the create methods of commodity_pool_t, or
+ * implicitly by parsing a commoditized amount.
+ */
+ typedef std::map<string, commodity_t *> commodities_map;
+
+ commodities_map commodities;
+ commodity_t * null_commodity;
+ commodity_t * default_commodity;
+
+ bool keep_base; // --base
+
+ optional<path> price_db; // --price-db=
+ long quote_leeway; // --leeway=
+ bool get_quotes; // --download
+
+ static shared_ptr<commodity_pool_t> current_pool;
+
+ function<optional<price_point_t>
+ (commodity_t& commodity, const optional<commodity_t&>& in_terms_of)>
+ get_commodity_quote;
+
+ explicit commodity_pool_t();
+
+ virtual ~commodity_pool_t() {
+ TRACE_DTOR(commodity_pool_t);
+ foreach (commodities_map::value_type pair, commodities)
+ checked_delete(pair.second);
+ }
+
+ string make_qualified_name(const commodity_t& comm,
+ const annotation_t& details);
+
+ commodity_t * create(const string& symbol);
+ commodity_t * find(const string& name);
+ commodity_t * find_or_create(const string& symbol);
+
+ commodity_t * create(const string& symbol, const annotation_t& details);
+ commodity_t * find(const string& symbol, const annotation_t& details);
+ commodity_t * find_or_create(const string& symbol,
+ const annotation_t& details);
+
+ commodity_t * create(commodity_t& comm,
+ const annotation_t& details,
+ const string& mapping_key);
+
+ commodity_t * find_or_create(commodity_t& comm,
+ const annotation_t& details);
+
+ // Exchange one commodity for another, while recording the factored price.
+
+ void exchange(commodity_t& commodity,
+ const amount_t& per_unit_cost,
+ const datetime_t& moment);
+
+ cost_breakdown_t exchange(const amount_t& amount,
+ const amount_t& cost,
+ const bool is_per_unit = false,
+ const optional<datetime_t>& moment = none,
+ const optional<string>& tag = none);
+
+ // Parse commodity prices from a textual representation
+
+ optional<std::pair<commodity_t *, price_point_t> >
+ parse_price_directive(char * line, bool do_not_add_price = false);
+
+ commodity_t *
+ parse_price_expression(const std::string& str,
+ const bool add_prices = true,
+ const optional<datetime_t>& moment = none);
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & current_pool;
+ ar & commodities;
+ ar & null_commodity;
+ ar & default_commodity;
+ ar & keep_base;
+ ar & price_db;
+ ar & quote_leeway;
+ ar & get_quotes;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+} // namespace ledger
+
+#endif // _POOL_H
diff --git a/src/post.cc b/src/post.cc
new file mode 100644
index 00000000..34284e1b
--- /dev/null
+++ b/src/post.cc
@@ -0,0 +1,576 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "post.h"
+#include "xact.h"
+#include "account.h"
+#include "journal.h"
+#include "interactive.h"
+#include "format.h"
+
+namespace ledger {
+
+bool post_t::has_tag(const string& tag) const
+{
+ if (item_t::has_tag(tag))
+ return true;
+ if (xact)
+ return xact->has_tag(tag);
+ return false;
+}
+
+bool post_t::has_tag(const mask_t& tag_mask,
+ const optional<mask_t>& value_mask) const
+{
+ if (item_t::has_tag(tag_mask, value_mask))
+ return true;
+ if (xact)
+ return xact->has_tag(tag_mask, value_mask);
+ return false;
+}
+
+optional<string> post_t::get_tag(const string& tag) const
+{
+ if (optional<string> value = item_t::get_tag(tag))
+ return value;
+ if (xact)
+ return xact->get_tag(tag);
+ return none;
+}
+
+optional<string> post_t::get_tag(const mask_t& tag_mask,
+ const optional<mask_t>& value_mask) const
+{
+ if (optional<string> value = item_t::get_tag(tag_mask, value_mask))
+ return value;
+ if (xact)
+ return xact->get_tag(tag_mask, value_mask);
+ return none;
+}
+
+date_t post_t::date() const
+{
+ if (xdata_ && is_valid(xdata_->date))
+ return xdata_->date;
+
+ if (item_t::use_effective_date) {
+ if (_date_eff)
+ return *_date_eff;
+ else if (xact && xact->_date_eff)
+ return *xact->_date_eff;
+ }
+
+ if (! _date) {
+ assert(xact);
+ return xact->date();
+ }
+ return *_date;
+}
+
+optional<date_t> post_t::effective_date() const
+{
+ optional<date_t> date = item_t::effective_date();
+ if (! date && xact)
+ return xact->effective_date();
+ return date;
+}
+
+namespace {
+ value_t get_this(post_t& post) {
+ return value_t(static_cast<scope_t *>(&post));
+ }
+
+ value_t get_is_calculated(post_t& post) {
+ return post.has_flags(POST_CALCULATED);
+ }
+
+ value_t get_is_cost_calculated(post_t& post) {
+ return post.has_flags(POST_COST_CALCULATED);
+ }
+
+ value_t get_virtual(post_t& post) {
+ return post.has_flags(POST_VIRTUAL);
+ }
+
+ value_t get_real(post_t& post) {
+ return ! post.has_flags(POST_VIRTUAL);
+ }
+
+ value_t get_xact(post_t& post) {
+ return value_t(static_cast<scope_t *>(post.xact));
+ }
+
+ value_t get_code(post_t& post) {
+ if (post.xact->code)
+ return string_value(*post.xact->code);
+ else
+ return string_value(empty_string);
+ }
+
+ value_t get_payee(post_t& post) {
+ return string_value(post.xact->payee);
+ }
+
+ value_t get_note(post_t& post) {
+ string note = post.note ? *post.note : empty_string;
+ note += post.xact->note ? *post.xact->note : empty_string;
+ return string_value(note);
+ }
+
+ value_t get_magnitude(post_t& post) {
+ return post.xact->magnitude();
+ }
+ value_t get_idstring(post_t& post) {
+ return string_value(post.xact->idstring());
+ }
+ value_t get_id(post_t& post) {
+ return string_value(post.xact->id());
+ }
+
+ value_t get_amount(post_t& post) {
+ if (post.has_xdata() && post.xdata().has_flags(POST_EXT_COMPOUND))
+ return post.xdata().compound_value;
+ else if (post.amount.is_null())
+ return 0L;
+ else
+ return post.amount;
+ }
+
+ value_t get_use_direct_amount(post_t& post) {
+ return post.has_xdata() && post.xdata().has_flags(POST_EXT_DIRECT_AMT);
+ }
+
+ value_t get_commodity(post_t& post) {
+ return string_value(post.amount.commodity().symbol());
+ }
+
+ value_t get_commodity_is_primary(post_t& post) {
+ return post.amount.commodity().has_flags(COMMODITY_PRIMARY);
+ }
+
+ value_t get_has_cost(post_t& post) {
+ return post.cost ? true : false;
+ }
+
+ value_t get_cost(post_t& post) {
+ if (post.cost)
+ return *post.cost;
+ else if (post.has_xdata() &&
+ post.xdata().has_flags(POST_EXT_COMPOUND))
+ return post.xdata().compound_value;
+ else if (post.amount.is_null())
+ return 0L;
+ else
+ return post.amount;
+ }
+
+ value_t get_total(post_t& post) {
+ if (post.xdata_ && ! post.xdata_->total.is_null())
+ return post.xdata_->total;
+ else if (post.amount.is_null())
+ return 0L;
+ else
+ return post.amount;
+ }
+
+ value_t get_count(post_t& post) {
+ if (post.xdata_)
+ return long(post.xdata_->count);
+ else
+ return 1L;
+ }
+
+ value_t get_account(call_scope_t& scope)
+ {
+ in_context_t<post_t> env(scope, "&v");
+
+ string name;
+
+ if (env.has(0)) {
+ if (env.value_at(0).is_long()) {
+ if (env.get<long>(0) > 2)
+ name = format_t::truncate(env->reported_account()->fullname(),
+ env.get<long>(0) - 2,
+ 2 /* account_abbrev_length */);
+ else
+ name = env->reported_account()->fullname();
+ } else {
+ account_t * account = NULL;
+ account_t * master = env->account;
+ while (master->parent)
+ master = master->parent;
+
+ if (env.value_at(0).is_string()) {
+ name = env.get<string>(0);
+ account = master->find_account(name, false);
+ }
+ else if (env.value_at(0).is_mask()) {
+ name = env.get<mask_t>(0).str();
+ account = master->find_account_re(name);
+ }
+ else {
+ throw_(std::runtime_error,
+ _("Expected string or mask for argument 1, but received %1")
+ << env.value_at(0).label());
+ }
+
+ if (! account)
+ throw_(std::runtime_error,
+ _("Could not find an account matching ") << env.value_at(0));
+ else
+ return value_t(static_cast<scope_t *>(account));
+ }
+ } else {
+ name = env->reported_account()->fullname();
+ }
+
+ if (env->has_flags(POST_VIRTUAL)) {
+ if (env->must_balance())
+ name = string("[") + name + "]";
+ else
+ name = string("(") + name + ")";
+ }
+ return string_value(name);
+ }
+
+ value_t get_account_base(post_t& post) {
+ return string_value(post.reported_account()->name);
+ }
+
+ value_t get_account_depth(post_t& post) {
+ return long(post.reported_account()->depth);
+ }
+
+ value_t get_datetime(post_t& post) {
+ return post.xdata().datetime;
+ }
+
+ template <value_t (*Func)(post_t&)>
+ value_t get_wrapper(call_scope_t& scope) {
+ return (*Func)(find_scope<post_t>(scope));
+ }
+}
+
+expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
+{
+ if (kind != symbol_t::FUNCTION)
+ return item_t::lookup(kind, name);
+
+ switch (name[0]) {
+ case 'a':
+ if (name[1] == '\0' || name == "amount")
+ return WRAP_FUNCTOR(get_wrapper<&get_amount>);
+ else if (name == "account")
+ return WRAP_FUNCTOR(get_account);
+ else if (name == "account_base")
+ return WRAP_FUNCTOR(get_wrapper<&get_account_base>);
+ break;
+
+ case 'b':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_cost>);
+ break;
+
+ case 'c':
+ if (name == "code")
+ return WRAP_FUNCTOR(get_wrapper<&get_code>);
+ else if (name == "cost")
+ return WRAP_FUNCTOR(get_wrapper<&get_cost>);
+ else if (name == "cost_calculated")
+ return WRAP_FUNCTOR(get_wrapper<&get_is_cost_calculated>);
+ else if (name == "count")
+ return WRAP_FUNCTOR(get_wrapper<&get_count>);
+ else if (name == "calculated")
+ return WRAP_FUNCTOR(get_wrapper<&get_is_calculated>);
+ else if (name == "commodity")
+ return WRAP_FUNCTOR(get_wrapper<&get_commodity>);
+ break;
+
+ case 'd':
+ if (name == "depth")
+ return WRAP_FUNCTOR(get_wrapper<&get_account_depth>);
+ else if (name == "datetime")
+ return WRAP_FUNCTOR(get_wrapper<&get_datetime>);
+ break;
+
+ case 'h':
+ if (name == "has_cost")
+ return WRAP_FUNCTOR(get_wrapper<&get_has_cost>);
+ break;
+
+ case 'i':
+ if (name == "index")
+ return WRAP_FUNCTOR(get_wrapper<&get_count>);
+ else if (name == "id")
+ return WRAP_FUNCTOR(get_wrapper<&get_id>);
+ else if (name == "idstring")
+ return WRAP_FUNCTOR(get_wrapper<&get_idstring>);
+ break;
+
+ case 'm':
+ if (name == "magnitude")
+ return WRAP_FUNCTOR(get_wrapper<&get_magnitude>);
+ break;
+
+ case 'n':
+ if (name == "note")
+ return WRAP_FUNCTOR(get_wrapper<&get_note>);
+ else if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_count>);
+ break;
+
+ case 'p':
+ if (name == "post")
+ return WRAP_FUNCTOR(get_wrapper<&get_this>);
+ else if (name == "payee")
+ return WRAP_FUNCTOR(get_wrapper<&get_payee>);
+ else if (name == "primary")
+ return WRAP_FUNCTOR(get_wrapper<&get_commodity_is_primary>);
+ else if (name == "parent")
+ return WRAP_FUNCTOR(get_wrapper<&get_xact>);
+ break;
+
+ case 'r':
+ if (name == "real")
+ return WRAP_FUNCTOR(get_wrapper<&get_real>);
+ break;
+
+ case 't':
+ if (name == "total")
+ return WRAP_FUNCTOR(get_wrapper<&get_total>);
+ break;
+
+ case 'u':
+ if (name == "use_direct_amount")
+ return WRAP_FUNCTOR(get_wrapper<&get_use_direct_amount>);
+ break;
+
+ case 'v':
+ if (name == "virtual")
+ return WRAP_FUNCTOR(get_wrapper<&get_virtual>);
+ break;
+
+ case 'x':
+ if (name == "xact")
+ return WRAP_FUNCTOR(get_wrapper<&get_xact>);
+ break;
+
+ case 'N':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_count>);
+ break;
+
+ case 'O':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_total>);
+ break;
+
+ case 'R':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_real>);
+ break;
+ }
+
+ return item_t::lookup(kind, name);
+}
+
+bool post_t::valid() const
+{
+ if (! xact) {
+ DEBUG("ledger.validate", "post_t: ! xact");
+ return false;
+ }
+
+ posts_list::const_iterator i =
+ std::find(xact->posts.begin(),
+ xact->posts.end(), this);
+ if (i == xact->posts.end()) {
+ DEBUG("ledger.validate", "post_t: ! found");
+ return false;
+ }
+
+ if (! account) {
+ DEBUG("ledger.validate", "post_t: ! account");
+ return false;
+ }
+
+ if (! amount.valid()) {
+ DEBUG("ledger.validate", "post_t: ! amount.valid()");
+ return false;
+ }
+
+ if (cost) {
+ if (! cost->valid()) {
+ DEBUG("ledger.validate", "post_t: cost && ! cost->valid()");
+ return false;
+ }
+ if (! cost->keep_precision()) {
+ DEBUG("ledger.validate", "post_t: ! cost->keep_precision()");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void post_t::add_to_value(value_t& value, const optional<expr_t&>& expr) const
+{
+ if (xdata_ && xdata_->has_flags(POST_EXT_COMPOUND)) {
+ add_or_set_value(value, xdata_->compound_value);
+ }
+ else if (expr) {
+ bind_scope_t bound_scope(*expr->get_context(),
+ const_cast<post_t&>(*this));
+#if 1
+ value_t temp(expr->calc(bound_scope));
+ add_or_set_value(value, temp);
+#else
+ if (! xdata_) xdata_ = xdata_t();
+ xdata_->value = expr->calc(bound_scope);
+ xdata_->add_flags(POST_EXT_COMPOUND);
+
+ add_or_set_value(value, xdata_->value);
+#endif
+ }
+ else if (xdata_ && xdata_->has_flags(POST_EXT_VISITED) &&
+ ! xdata_->visited_value.is_null()) {
+ add_or_set_value(value, xdata_->visited_value);
+ }
+ else {
+ add_or_set_value(value, amount);
+ }
+}
+
+void post_t::set_reported_account(account_t * account)
+{
+ xdata().account = account;
+ account->xdata().reported_posts.push_back(this);
+}
+
+void to_xml(std::ostream& out, const post_t& post)
+{
+ push_xml x(out, "posting", true);
+
+ if (post.state() == item_t::CLEARED)
+ out << " state=\"cleared\"";
+ else if (post.state() == item_t::PENDING)
+ out << " state=\"pending\"";
+
+ if (post.has_flags(POST_VIRTUAL))
+ out << " virtual=\"true\"";
+ if (post.has_flags(ITEM_GENERATED))
+ out << " generated=\"true\"";
+
+ x.close_attrs();
+
+ if (post._date) {
+ push_xml y(out, "date");
+ to_xml(out, *post._date, false);
+ }
+ if (post._date_eff) {
+ push_xml y(out, "effective-date");
+ to_xml(out, *post._date_eff, false);
+ }
+
+ if (post.account) {
+ push_xml y(out, "account", true);
+
+ out << " ref=\"";
+ out.width(sizeof(unsigned long) * 2);
+ out.fill('0');
+ out << std::hex << reinterpret_cast<unsigned long>(post.account);
+ out << '"';
+ y.close_attrs();
+
+ {
+ push_xml z(out, "name");
+ out << z.guard(post.account->fullname());
+ }
+ }
+
+ {
+ push_xml y(out, "post-amount");
+ if (post.has_xdata() && post.xdata().has_flags(POST_EXT_COMPOUND))
+ to_xml(out, post.xdata().compound_value);
+ else
+ to_xml(out, post.amount);
+ }
+
+ if (post.cost) {
+ push_xml y(out, "cost");
+ to_xml(out, *post.cost);
+ }
+
+ if (post.assigned_amount) {
+ if (post.has_flags(POST_CALCULATED)) {
+ push_xml y(out, "balance-assertion");
+ to_xml(out, *post.assigned_amount);
+ } else {
+ push_xml y(out, "balance-assignment");
+ to_xml(out, *post.assigned_amount);
+ }
+ }
+
+ if (post.note) {
+ push_xml y(out, "note");
+ out << y.guard(*post.note);
+ }
+
+ if (post.metadata) {
+ push_xml y(out, "metadata");
+ foreach (const item_t::string_map::value_type& pair, *post.metadata) {
+ if (pair.second) {
+ push_xml z(out, "variable");
+ {
+ push_xml z(out, "key");
+ out << y.guard(pair.first);
+ }
+ {
+ push_xml z(out, "value");
+ out << y.guard(*pair.second);
+ }
+ } else {
+ push_xml z(out, "tag");
+ out << y.guard(pair.first);
+ }
+ }
+ }
+
+ if (post.xdata_ && ! post.xdata_->total.is_null()) {
+ push_xml y(out, "total");
+ to_xml(out, post.xdata_->total);
+ }
+}
+
+} // namespace ledger
diff --git a/src/post.h b/src/post.h
new file mode 100644
index 00000000..a0ab5ffd
--- /dev/null
+++ b/src/post.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup data
+ */
+
+/**
+ * @file post.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _POST_H
+#define _POST_H
+
+#include "item.h"
+
+namespace ledger {
+
+class xact_t;
+class account_t;
+
+class post_t : public item_t
+{
+public:
+#define POST_VIRTUAL 0x10 // the account was specified with (parens)
+#define POST_MUST_BALANCE 0x20 // posting must balance in the transaction
+#define POST_CALCULATED 0x40 // posting's amount was calculated
+#define POST_COST_CALCULATED 0x80 // posting's cost was calculated
+
+ xact_t * xact; // only set for posts of regular xacts
+ account_t * account;
+
+ amount_t amount; // can be null until finalization
+ optional<expr_t> amount_expr;
+ optional<amount_t> cost;
+ optional<amount_t> assigned_amount;
+
+ post_t(account_t * _account = NULL,
+ flags_t _flags = ITEM_NORMAL)
+ : item_t(_flags),
+ xact(NULL), account(_account)
+ {
+ TRACE_CTOR(post_t, "account_t *, flags_t");
+ }
+ post_t(account_t * _account,
+ const amount_t& _amount,
+ flags_t _flags = ITEM_NORMAL,
+ const optional<string>& _note = none)
+ : item_t(_flags, _note),
+ xact(NULL), account(_account), amount(_amount)
+ {
+ TRACE_CTOR(post_t, "account_t *, const amount_t&, flags_t, const optional<string>&");
+ }
+ post_t(const post_t& post)
+ : item_t(post),
+ xact(post.xact),
+ account(post.account),
+ amount(post.amount),
+ cost(post.cost),
+ assigned_amount(post.assigned_amount),
+ xdata_(post.xdata_)
+ {
+ TRACE_CTOR(post_t, "copy");
+ }
+ virtual ~post_t() {
+ TRACE_DTOR(post_t);
+ }
+
+ virtual bool has_tag(const string& tag) const;
+ virtual bool has_tag(const mask_t& tag_mask,
+ const optional<mask_t>& value_mask = none) const;
+
+ virtual optional<string> get_tag(const string& tag) const;
+ virtual optional<string> get_tag(const mask_t& tag_mask,
+ const optional<mask_t>& value_mask = none) const;
+
+ virtual date_t date() const;
+ virtual optional<date_t> effective_date() const;
+
+ bool must_balance() const {
+ return ! has_flags(POST_VIRTUAL) || has_flags(POST_MUST_BALANCE);
+ }
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
+
+ bool valid() const;
+
+ struct xdata_t : public supports_flags<uint_least16_t>
+ {
+#define POST_EXT_RECEIVED 0x0001
+#define POST_EXT_HANDLED 0x0002
+#define POST_EXT_DISPLAYED 0x0004
+#define POST_EXT_DIRECT_AMT 0x0008
+#define POST_EXT_SORT_CALC 0x0010
+#define POST_EXT_COMPOUND 0x0020
+#define POST_EXT_VISITED 0x0040
+#define POST_EXT_MATCHES 0x0080
+#define POST_EXT_CONSIDERED 0x0100
+
+ value_t visited_value;
+ value_t compound_value;
+ value_t total;
+ std::size_t count;
+ date_t date;
+ datetime_t datetime;
+ account_t * account;
+
+ std::list<sort_value_t> sort_values;
+
+ xdata_t()
+ : supports_flags<uint_least16_t>(), count(0), account(NULL) {
+ TRACE_CTOR(post_t::xdata_t, "");
+ }
+ xdata_t(const xdata_t& other)
+ : supports_flags<uint_least16_t>(other.flags()),
+ visited_value(other.visited_value),
+ compound_value(other.compound_value),
+ total(other.total),
+ count(other.count),
+ date(other.date),
+ account(other.account),
+ sort_values(other.sort_values)
+ {
+ TRACE_CTOR(post_t::xdata_t, "copy");
+ }
+ ~xdata_t() throw() {
+ TRACE_DTOR(post_t::xdata_t);
+ }
+ };
+
+ // This variable holds optional "extended data" which is usually produced
+ // only during reporting, and only for the posting set being reported.
+ // It's a memory-saving measure to delay allocation until the last possible
+ // moment.
+ mutable optional<xdata_t> xdata_;
+
+ bool has_xdata() const {
+ return xdata_;
+ }
+ void clear_xdata() {
+ xdata_ = none;
+ }
+ xdata_t& xdata() {
+ if (! xdata_)
+ xdata_ = xdata_t();
+ return *xdata_;
+ }
+ const xdata_t& xdata() const {
+ return const_cast<post_t *>(this)->xdata();
+ }
+
+ void add_to_value(value_t& value,
+ const optional<expr_t&>& expr = none) const;
+
+ void set_reported_account(account_t * account);
+
+ account_t * reported_account() {
+ if (xdata_)
+ if (account_t * acct = xdata_->account)
+ return acct;
+ return account;
+ }
+
+ const account_t * reported_account() const {
+ return const_cast<post_t *>(this)->reported_account();
+ }
+
+ friend class xact_t;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<item_t>(*this);
+ ar & xact;
+ ar & account;
+ ar & amount;
+ ar & amount_expr;
+ ar & cost;
+ ar & assigned_amount;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+void to_xml(std::ostream& out, const post_t& post);
+
+} // namespace ledger
+
+#endif // _POST_H
diff --git a/src/precmd.cc b/src/precmd.cc
new file mode 100644
index 00000000..31249016
--- /dev/null
+++ b/src/precmd.cc
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "precmd.h"
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "query.h"
+#include "session.h"
+#include "report.h"
+#include "format.h"
+
+namespace ledger {
+
+namespace {
+ post_t * get_sample_xact(report_t& report)
+ {
+ {
+ string str;
+ {
+ std::ostringstream buf;
+
+ buf << "2004/05/27 Book Store\n"
+ << " ; This note applies to all postings. :SecondTag:\n"
+ << " Expenses:Books 20 BOOK @ $10\n"
+ << " ; Metadata: Some Value\n"
+ << " ; :ExampleTag:\n"
+ << " ; Here follows a note describing the posting.\n"
+ << " Liabilities:MasterCard $-200.00\n";
+
+ str = buf.str();
+ }
+
+ std::ostream& out(report.output_stream);
+
+ out << _("--- Context is first posting of the following transaction ---")
+ << std::endl << str << std::endl;
+ {
+ std::istringstream in(str);
+ report.session.journal->parse(in, report.session);
+ report.session.journal->clear_xdata();
+ }
+ }
+ xact_t * first = report.session.journal->xacts.front();
+ return first->posts.front();
+ }
+}
+
+value_t parse_command(call_scope_t& args)
+{
+ string arg = join_args(args);
+ if (arg.empty()) {
+ throw std::logic_error(_("Usage: parse TEXT"));
+ return 1L;
+ }
+
+ report_t& report(find_scope<report_t>(args));
+ std::ostream& out(report.output_stream);
+
+ post_t * post = get_sample_xact(report);
+
+ out << _("--- Input expression ---") << std::endl;
+ out << arg << std::endl;
+
+ out << std::endl << _("--- Text as parsed ---") << std::endl;
+ expr_t expr(arg);
+ expr.print(out);
+ out << std::endl;
+
+ out << std::endl << _("--- Expression tree ---") << std::endl;
+ expr.dump(out);
+
+ bind_scope_t bound_scope(args, *post);
+ expr.compile(bound_scope);
+ out << std::endl << _("--- Compiled tree ---") << std::endl;
+ expr.dump(out);
+
+ out << std::endl << _("--- Calculated value ---") << std::endl;
+ value_t result(expr.calc());
+ result.strip_annotations(report.what_to_keep()).dump(out);
+ out << std::endl;
+
+ return NULL_VALUE;
+}
+
+value_t eval_command(call_scope_t& args)
+{
+ report_t& report(find_scope<report_t>(args));
+ expr_t expr(join_args(args));
+ value_t result(expr.calc(args).strip_annotations(report.what_to_keep()));
+
+ if (! result.is_null())
+ report.output_stream << result << std::endl;
+
+ return NULL_VALUE;
+}
+
+value_t format_command(call_scope_t& args)
+{
+ string arg = join_args(args);
+ if (arg.empty()) {
+ throw std::logic_error(_("Usage: format TEXT"));
+ return 1L;
+ }
+
+ report_t& report(find_scope<report_t>(args));
+ std::ostream& out(report.output_stream);
+
+ post_t * post = get_sample_xact(report);
+
+ out << _("--- Input format string ---") << std::endl;
+ out << arg << std::endl << std::endl;
+
+ out << _("--- Format elements ---") << std::endl;
+ format_t fmt(arg);
+ fmt.dump(out);
+
+ out << std::endl << _("--- Formatted string ---") << std::endl;
+ bind_scope_t bound_scope(args, *post);
+ out << '"';
+ out << fmt(bound_scope);
+ out << "\"\n";
+
+ return NULL_VALUE;
+}
+
+value_t period_command(call_scope_t& args)
+{
+ string arg = join_args(args);
+ if (arg.empty()) {
+ throw std::logic_error(_("Usage: period TEXT"));
+ return 1L;
+ }
+
+ report_t& report(find_scope<report_t>(args));
+ std::ostream& out(report.output_stream);
+
+ show_period_tokens(out, arg);
+ out << std::endl;
+
+ date_interval_t interval(arg);
+ interval.dump(out, report.session.current_year);
+
+ return NULL_VALUE;
+}
+
+value_t args_command(call_scope_t& args)
+{
+ report_t& report(find_scope<report_t>(args));
+ std::ostream& out(report.output_stream);
+
+ out << _("--- Input arguments ---") << std::endl;
+ args.value().dump(out);
+ out << std::endl << std::endl;
+
+ query_t query(args.value(), report.what_to_keep());
+ if (query) {
+ call_scope_t sub_args(static_cast<scope_t&>(args));
+ sub_args.push_back(string_value(query.text()));
+
+ parse_command(sub_args);
+ }
+
+ if (query.tokens_remaining()) {
+ out << std::endl << _("====== Display predicate ======")
+ << std::endl << std::endl;
+
+ query.parse_again();
+
+ if (query) {
+ call_scope_t disp_sub_args(static_cast<scope_t&>(args));
+ disp_sub_args.push_back(string_value(query.text()));
+
+ parse_command(disp_sub_args);
+ }
+ }
+
+ return NULL_VALUE;
+}
+
+} // namespace ledger
diff --git a/src/precmd.h b/src/precmd.h
new file mode 100644
index 00000000..e0f81cf8
--- /dev/null
+++ b/src/precmd.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup report
+ */
+
+/**
+ * @file precmd.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _PRECMD_H
+#define _PRECMD_H
+
+#include "value.h"
+
+namespace ledger {
+
+class call_scope_t;
+
+value_t parse_command(call_scope_t& args);
+value_t eval_command(call_scope_t& args);
+value_t format_command(call_scope_t& args);
+value_t period_command(call_scope_t& args);
+value_t args_command(call_scope_t& args);
+
+} // namespace ledger
+
+#endif // _PRECMD_H
diff --git a/src/predicate.cc b/src/predicate.cc
new file mode 100644
index 00000000..4da4decf
--- /dev/null
+++ b/src/predicate.cc
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "predicate.h"
+#include "query.h"
+#include "op.h"
+
+namespace ledger {
+
+predicate_t::predicate_t(const query_t& other)
+ : expr_t(other), what_to_keep(other.what_to_keep)
+{
+ TRACE_CTOR(predicate_t, "query_t");
+}
+
+} // namespace ledger
diff --git a/src/predicate.h b/src/predicate.h
new file mode 100644
index 00000000..b3b81f9b
--- /dev/null
+++ b/src/predicate.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup expr
+ */
+
+/**
+ * @file predicate.h
+ * @author John Wiegley
+ *
+ * @ingroup expr
+ */
+#ifndef _PREDICATE_H
+#define _PREDICATE_H
+
+#include "expr.h"
+#include "commodity.h"
+#include "annotate.h"
+
+namespace ledger {
+
+class query_t;
+
+class predicate_t : public expr_t
+{
+public:
+ keep_details_t what_to_keep;
+
+ predicate_t(const keep_details_t& _what_to_keep = keep_details_t())
+ : what_to_keep(_what_to_keep) {
+ TRACE_CTOR(predicate_t, "");
+ }
+ predicate_t(const predicate_t& other)
+ : expr_t(other), what_to_keep(other.what_to_keep) {
+ TRACE_CTOR(predicate_t, "copy");
+ }
+ predicate_t(const query_t& other);
+
+ predicate_t(const string& str, const keep_details_t& _what_to_keep,
+ const parse_flags_t& flags = PARSE_DEFAULT)
+ : expr_t(str, flags), what_to_keep(_what_to_keep) {
+ TRACE_CTOR(predicate_t, "string, keep_details_t, parse_flags_t");
+ }
+ predicate_t(std::istream& in, const keep_details_t& _what_to_keep,
+ const parse_flags_t& flags = PARSE_DEFAULT)
+ : expr_t(in, flags), what_to_keep(_what_to_keep) {
+ TRACE_CTOR(predicate_t, "std::istream&, keep_details_t, parse_flags_t");
+ }
+ virtual ~predicate_t() {
+ TRACE_DTOR(predicate_t);
+ }
+
+ virtual value_t real_calc(scope_t& scope) {
+ return (*this ?
+ expr_t::real_calc(scope)
+ .strip_annotations(what_to_keep)
+ .to_boolean() :
+ true);
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<expr_t>(*this);
+ ar & what_to_keep;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+} // namespace ledger
+
+#endif // _PREDICATE_H
diff --git a/src/pstream.h b/src/pstream.h
new file mode 100644
index 00000000..00caf4e0
--- /dev/null
+++ b/src/pstream.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup util
+ */
+
+/**
+ * @file pstream.h
+ * @author John Wiegley
+ *
+ * @ingroup util
+ */
+#ifndef _PSTREAM_H
+#define _PSTREAM_H
+
+//#include <istream>
+//#include <streambuf>
+
+class ptristream : public std::istream
+{
+ class ptrinbuf : public std::streambuf
+ {
+ ptrinbuf(const ptrinbuf&);
+ ptrinbuf& operator=(const ptrinbuf&);
+
+ protected:
+ char * ptr;
+ std::size_t len;
+
+ public:
+ ptrinbuf(char * _ptr, std::size_t _len) : ptr(_ptr), len(_len) {
+ if (*ptr && len == 0)
+ len = std::strlen(ptr);
+
+ setg(ptr, // beginning of putback area
+ ptr, // read position
+ ptr+len); // end position
+ }
+
+ protected:
+ virtual int_type underflow() {
+ // is read position before end of buffer?
+ if (gptr() < egptr())
+ return traits_type::to_int_type(*gptr());
+ else
+ return EOF;
+ }
+
+ virtual pos_type seekoff(off_type off, ios_base::seekdir way,
+ ios_base::openmode)
+ {
+ switch (way) {
+ case std::ios::cur:
+ setg(ptr, gptr()+off, ptr+len);
+ break;
+ case std::ios::beg:
+ setg(ptr, ptr+off, ptr+len);
+ break;
+ case std::ios::end:
+ setg(ptr, egptr()+off, ptr+len);
+ break;
+
+ default:
+ return pos_type(off_type(-1));
+ }
+ return pos_type(gptr() - ptr);
+ }
+ };
+
+protected:
+ ptrinbuf buf;
+
+public:
+ ptristream(char * ptr, std::size_t len = 0)
+ : std::istream(0), buf(ptr, len) {
+ rdbuf(&buf);
+ }
+};
+
+#endif // _PSTREAM_H
diff --git a/src/py_account.cc b/src/py_account.cc
new file mode 100644
index 00000000..056cd722
--- /dev/null
+++ b/src/py_account.cc
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "pyutils.h"
+#include "account.h"
+#include "post.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+namespace {
+
+ long accounts_len(account_t& account)
+ {
+ return account.accounts.size();
+ }
+
+ account_t& accounts_getitem(account_t& account, long i)
+ {
+ static long last_index = 0;
+ static account_t * last_account = NULL;
+ static accounts_map::iterator elem;
+
+ long len = account.accounts.size();
+
+ if (labs(i) >= len) {
+ PyErr_SetString(PyExc_IndexError, _("Index out of range"));
+ throw_error_already_set();
+ }
+
+ if (&account == last_account && i == last_index + 1) {
+ last_index = i;
+ return *(*++elem).second;
+ }
+
+ long x = i < 0 ? len + i : i;
+ elem = account.accounts.begin();
+ while (--x >= 0)
+ elem++;
+
+ last_account = &account;
+ last_index = i;
+
+ return *(*elem).second;
+ }
+
+ account_t * py_find_account_1(journal_t& journal, const string& name)
+ {
+ return journal.find_account(name);
+ }
+
+ account_t * py_find_account_2(journal_t& journal, const string& name,
+ const bool auto_create)
+ {
+ return journal.find_account(name, auto_create);
+ }
+
+ account_t::xdata_t& py_xdata(account_t& account) {
+ return account.xdata();
+ }
+
+ PyObject * py_account_unicode(account_t& account) {
+ return str_to_py_unicode(account.fullname());
+ }
+
+} // unnamed namespace
+
+void export_account()
+{
+ scope().attr("ACCOUNT_EXT_SORT_CALC") = ACCOUNT_EXT_SORT_CALC;
+ scope().attr("ACCOUNT_EXT_HAS_NON_VIRTUALS") = ACCOUNT_EXT_HAS_NON_VIRTUALS;
+ scope().attr("ACCOUNT_EXT_HAS_UNB_VIRTUALS") = ACCOUNT_EXT_HAS_UNB_VIRTUALS;
+ scope().attr("ACCOUNT_EXT_AUTO_VIRTUALIZE") = ACCOUNT_EXT_AUTO_VIRTUALIZE;
+ scope().attr("ACCOUNT_EXT_VISITED") = ACCOUNT_EXT_VISITED;
+ scope().attr("ACCOUNT_EXT_MATCHING") = ACCOUNT_EXT_MATCHING;
+ scope().attr("ACCOUNT_EXT_TO_DISPLAY") = ACCOUNT_EXT_TO_DISPLAY;
+ scope().attr("ACCOUNT_EXT_DISPLAYED") = ACCOUNT_EXT_DISPLAYED;
+
+ class_< account_t::xdata_t::details_t > ("AccountXDataDetails")
+ .def_readonly("total", &account_t::xdata_t::details_t::total)
+ .def_readonly("calculated", &account_t::xdata_t::details_t::calculated)
+ .def_readonly("gathered", &account_t::xdata_t::details_t::gathered)
+
+ .def_readonly("posts_count", &account_t::xdata_t::details_t::posts_count)
+ .def_readonly("posts_virtuals_count",
+ &account_t::xdata_t::details_t::posts_virtuals_count)
+ .def_readonly("posts_cleared_count",
+ &account_t::xdata_t::details_t::posts_cleared_count)
+ .def_readonly("posts_last_7_count",
+ &account_t::xdata_t::details_t::posts_last_7_count)
+ .def_readonly("posts_last_30_count",
+ &account_t::xdata_t::details_t::posts_last_30_count)
+ .def_readonly("posts_this_month_count",
+ &account_t::xdata_t::details_t::posts_this_month_count)
+
+ .def_readonly("earliest_post",
+ &account_t::xdata_t::details_t::earliest_post)
+ .def_readonly("earliest_cleared_post",
+ &account_t::xdata_t::details_t::earliest_cleared_post)
+ .def_readonly("latest_post",
+ &account_t::xdata_t::details_t::latest_post)
+ .def_readonly("latest_cleared_post",
+ &account_t::xdata_t::details_t::latest_cleared_post)
+
+ .def_readonly("filenames", &account_t::xdata_t::details_t::filenames)
+ .def_readonly("accounts_referenced",
+ &account_t::xdata_t::details_t::accounts_referenced)
+ .def_readonly("payees_referenced",
+ &account_t::xdata_t::details_t::payees_referenced)
+
+ .def(self += self)
+
+ .def("update", &account_t::xdata_t::details_t::update)
+ ;
+
+ class_< account_t::xdata_t > ("AccountXData")
+#if 1
+ .add_property("flags",
+ &supports_flags<uint_least16_t>::flags,
+ &supports_flags<uint_least16_t>::set_flags)
+ .def("has_flags", &supports_flags<uint_least16_t>::has_flags)
+ .def("clear_flags", &supports_flags<uint_least16_t>::clear_flags)
+ .def("add_flags", &supports_flags<uint_least16_t>::add_flags)
+ .def("drop_flags", &supports_flags<uint_least16_t>::drop_flags)
+#endif
+
+ .def_readonly("self_details", &account_t::xdata_t::self_details)
+ .def_readonly("family_details", &account_t::xdata_t::family_details)
+ .def_readonly("reported_posts", &account_t::xdata_t::reported_posts)
+ .def_readonly("sort_values", &account_t::xdata_t::sort_values)
+ ;
+
+ scope().attr("ACCOUNT_NORMAL") = ACCOUNT_NORMAL;
+ scope().attr("ACCOUNT_KNOWN") = ACCOUNT_KNOWN;
+ scope().attr("ACCOUNT_TEMP") = ACCOUNT_TEMP;
+
+ class_< account_t > ("Account")
+#if 1
+ .add_property("flags",
+ &supports_flags<>::flags,
+ &supports_flags<>::set_flags)
+ .def("has_flags", &supports_flags<>::has_flags)
+ .def("clear_flags", &supports_flags<>::clear_flags)
+ .def("add_flags", &supports_flags<>::add_flags)
+ .def("drop_flags", &supports_flags<>::drop_flags)
+#endif
+
+ .add_property("parent",
+ make_getter(&account_t::parent,
+ return_internal_reference<>()))
+
+ .def_readwrite("name", &account_t::name)
+ .def_readwrite("note", &account_t::note)
+ .def_readonly("depth", &account_t::depth)
+
+ .def("__str__", &account_t::fullname)
+ .def("__unicode__", py_account_unicode)
+
+ .def("fullname", &account_t::fullname)
+ .def("partial_name", &account_t::partial_name)
+
+ .def("add_account", &account_t::add_account)
+ .def("remove_account", &account_t::remove_account)
+
+ .def("find_account", &account_t::find_account,
+ return_internal_reference<>())
+ .def("find_account_re", &account_t::find_account,
+ return_internal_reference<>())
+
+ .def("add_post", &account_t::add_post)
+ .def("remove_post", &account_t::remove_post)
+
+ .def("valid", &account_t::valid)
+
+ .def("__len__", accounts_len)
+ .def("__getitem__", accounts_getitem, return_internal_reference<>())
+
+ .def("__iter__", range<return_internal_reference<> >
+ (&account_t::accounts_begin, &account_t::accounts_end))
+ .def("accounts", range<return_internal_reference<> >
+ (&account_t::accounts_begin, &account_t::accounts_end))
+ .def("posts", range<return_internal_reference<> >
+ (&account_t::posts_begin, &account_t::posts_end))
+
+ .def("has_xdata", &account_t::has_xdata)
+ .def("clear_xdata", &account_t::clear_xdata)
+ .def("xdata", py_xdata,
+ return_internal_reference<>())
+
+ .def("amount", &account_t::amount)
+ .def("total", &account_t::total)
+
+ .def("self_details", &account_t::self_details,
+ return_internal_reference<>())
+ .def("family_details", &account_t::family_details,
+ return_internal_reference<>())
+
+ .def("has_xflags", &account_t::has_xflags)
+ .def("children_with_flags", &account_t::children_with_flags)
+ ;
+}
+
+} // namespace ledger
diff --git a/src/py_amount.cc b/src/py_amount.cc
new file mode 100644
index 00000000..8fb507a3
--- /dev/null
+++ b/src/py_amount.cc
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "pyutils.h"
+#include "pyfstream.h"
+#include "commodity.h"
+#include "annotate.h"
+#include "pool.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+namespace {
+
+ boost::optional<amount_t> py_value_0(const amount_t& amount) {
+ return amount.value(false, CURRENT_TIME());
+ }
+ boost::optional<amount_t> py_value_1(const amount_t& amount,
+ commodity_t& in_terms_of) {
+ return amount.value(false, CURRENT_TIME(), in_terms_of);
+ }
+ boost::optional<amount_t> py_value_2(const amount_t& amount,
+ commodity_t& in_terms_of,
+ datetime_t& moment) {
+ return amount.value(false, moment, in_terms_of);
+ }
+
+ void py_parse_2(amount_t& amount, object in, unsigned char flags) {
+ if (PyFile_Check(in.ptr())) {
+ pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr()));
+ amount.parse(instr, flags);
+ } else {
+ PyErr_SetString(PyExc_IOError,
+ _("Argument to amount.parse(file) is not a file object"));
+ }
+ }
+ void py_parse_1(amount_t& amount, object in) {
+ py_parse_2(amount, in, 0);
+ }
+
+ void py_parse_str_1(amount_t& amount, const string& str) {
+ amount.parse(str);
+ }
+ void py_parse_str_2(amount_t& amount, const string& str, unsigned char flags) {
+ amount.parse(str, flags);
+ }
+
+ void py_print(amount_t& amount, object out) {
+ if (PyFile_Check(out.ptr())) {
+ pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr()));
+ amount.print(outstr);
+ } else {
+ PyErr_SetString(PyExc_IOError,
+ _("Argument to amount.print_(file) is not a file object"));
+ }
+ }
+
+ annotation_t& py_amount_annotation(amount_t& amount) {
+ return amount.annotation();
+ }
+
+ amount_t py_strip_annotations_0(amount_t& amount) {
+ return amount.strip_annotations(keep_details_t());
+ }
+ amount_t py_strip_annotations_1(amount_t& amount, const keep_details_t& keep) {
+ return amount.strip_annotations(keep);
+ }
+
+ PyObject * py_amount_unicode(amount_t& amount) {
+ return str_to_py_unicode(amount.to_string());
+ }
+
+} // unnamed namespace
+
+#define EXC_TRANSLATOR(type) \
+ void exc_translate_ ## type(const type& err) { \
+ PyErr_SetString(PyExc_ArithmeticError, err.what()); \
+ }
+
+EXC_TRANSLATOR(amount_error)
+
+void export_amount()
+{
+ class_< amount_t > ("Amount")
+ .def("initialize", &amount_t::initialize) // only for the PyUnitTests
+ .staticmethod("initialize")
+ .def("shutdown", &amount_t::shutdown)
+ .staticmethod("shutdown")
+
+ .add_static_property("is_initialized",
+ make_getter(&amount_t::is_initialized),
+ make_setter(&amount_t::is_initialized))
+ .add_static_property("stream_fullstrings",
+ make_getter(&amount_t::stream_fullstrings),
+ make_setter(&amount_t::stream_fullstrings))
+
+ .def(init<long>())
+ .def(init<std::string>())
+
+ .def("exact", &amount_t::exact, args("value"),
+ _("Construct an amount object whose display precision is always equal to its\n\
+internal precision."))
+ .staticmethod("exact")
+
+ .def(init<amount_t>())
+
+ .def("compare", &amount_t::compare, args("amount"),
+ _("Compare two amounts for equality, returning <0, 0 or >0."))
+
+ .def(self == self)
+ .def(self == long())
+ .def(long() == self)
+
+ .def(self != self)
+ .def(self != long())
+ .def(long() != self)
+
+ .def(! self)
+
+ .def(self < self)
+ .def(self < long())
+ .def(long() < self)
+
+ .def(self <= self)
+ .def(self <= long())
+ .def(long() <= self)
+
+ .def(self > self)
+ .def(self > long())
+ .def(long() > self)
+
+ .def(self >= self)
+ .def(self >= long())
+ .def(long() >= self)
+
+ .def(self += self)
+ .def(self += long())
+
+ .def(self + self)
+ .def(self + long())
+ .def(long() + self)
+
+ .def(self -= self)
+ .def(self -= long())
+
+ .def(self - self)
+ .def(self - long())
+ .def(long() - self)
+
+ .def(self *= self)
+ .def(self *= long())
+
+ .def(self * self)
+ .def(self * long())
+ .def(long() * self)
+
+ .def(self /= self)
+ .def(self /= long())
+
+ .def(self / self)
+ .def(self / long())
+ .def(long() / self)
+
+ .add_property("precision", &amount_t::precision)
+ .add_property("display_precision", &amount_t::display_precision)
+ .add_property("keep_precision",
+ &amount_t::keep_precision,
+ &amount_t::set_keep_precision)
+
+ .def("negated", &amount_t::negated)
+ .def("in_place_negate", &amount_t::in_place_negate,
+ return_internal_reference<>())
+ .def(- self)
+
+ .def("abs", &amount_t::abs)
+ .def("__abs__", &amount_t::abs)
+
+ .def("inverted", &amount_t::inverted)
+
+ .def("rounded", &amount_t::rounded)
+ .def("in_place_round", &amount_t::in_place_round,
+ return_internal_reference<>())
+
+ .def("truncated", &amount_t::truncated)
+ .def("in_place_truncate", &amount_t::in_place_truncate,
+ return_internal_reference<>())
+
+ .def("floored", &amount_t::floored)
+ .def("in_place_floor", &amount_t::in_place_floor,
+ return_internal_reference<>())
+
+ .def("unrounded", &amount_t::unrounded)
+ .def("in_place_unround", &amount_t::in_place_unround,
+ return_internal_reference<>())
+
+ .def("reduced", &amount_t::reduced)
+ .def("in_place_reduce", &amount_t::in_place_reduce,
+ return_internal_reference<>())
+
+ .def("unreduced", &amount_t::unreduced)
+ .def("in_place_unreduce", &amount_t::in_place_unreduce,
+ return_internal_reference<>())
+
+ .def("value", py_value_0)
+ .def("value", py_value_1, args("in_terms_of"))
+ .def("value", py_value_2, args("in_terms_of", "moment"))
+
+ .def("price", &amount_t::price)
+
+ .def("sign", &amount_t::sign)
+ .def("__nonzero__", &amount_t::is_nonzero)
+ .def("is_nonzero", &amount_t::is_nonzero)
+ .def("is_zero", &amount_t::is_zero)
+ .def("is_realzero", &amount_t::is_realzero)
+ .def("is_null", &amount_t::is_null)
+
+ .def("to_double", &amount_t::to_double)
+ .def("__float__", &amount_t::to_double)
+ .def("to_long", &amount_t::to_long)
+ .def("__int__", &amount_t::to_long)
+ .def("fits_in_long", &amount_t::fits_in_long)
+
+ .def("__str__", &amount_t::to_string)
+ .def("to_string", &amount_t::to_string)
+ .def("__unicode__", py_amount_unicode)
+ .def("to_fullstring", &amount_t::to_fullstring)
+ .def("__repr__", &amount_t::to_fullstring)
+ .def("quantity_string", &amount_t::quantity_string)
+
+ .add_property("commodity",
+ make_function(&amount_t::commodity,
+ return_value_policy<reference_existing_object>()),
+ make_function(&amount_t::set_commodity,
+ with_custodian_and_ward<1, 2>()))
+ .def("has_commodity", &amount_t::has_commodity)
+ .def("clear_commodity", &amount_t::clear_commodity)
+
+ .def("number", &amount_t::number)
+
+ .def("annotate", &amount_t::annotate)
+ .def("has_annotation", &amount_t::has_annotation)
+ .add_property("annotation",
+ make_function(py_amount_annotation,
+ return_internal_reference<>()))
+ .def("strip_annotations", py_strip_annotations_0)
+ .def("strip_annotations", py_strip_annotations_1)
+
+ .def("parse", py_parse_1)
+ .def("parse", py_parse_2)
+ .def("parse", py_parse_str_1)
+ .def("parse", py_parse_str_2)
+
+ .def("parse_conversion", &amount_t::parse_conversion)
+ .staticmethod("parse_conversion")
+
+ .def("valid", &amount_t::valid)
+ ;
+
+ enum_< parse_flags_enum_t >("ParseFlags")
+ .value("Default", PARSE_DEFAULT)
+ .value("Partial", PARSE_PARTIAL)
+ .value("Single", PARSE_SINGLE)
+ .value("NoMigrate", PARSE_NO_MIGRATE)
+ .value("NoReduce", PARSE_NO_REDUCE)
+ .value("NoAssign", PARSE_NO_ASSIGN)
+ .value("NoDates", PARSE_NO_DATES)
+ .value("OpContext", PARSE_OP_CONTEXT)
+ .value("SoftFail", PARSE_SOFT_FAIL)
+ ;
+
+ register_optional_to_python<amount_t>();
+
+ implicitly_convertible<long, amount_t>();
+ implicitly_convertible<string, amount_t>();
+
+#define EXC_TRANSLATE(type) \
+ register_exception_translator<type>(&exc_translate_ ## type);
+
+ EXC_TRANSLATE(amount_error);
+}
+
+} // namespace ledger
diff --git a/src/py_balance.cc b/src/py_balance.cc
new file mode 100644
index 00000000..8c0c4c58
--- /dev/null
+++ b/src/py_balance.cc
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "pyutils.h"
+#include "pyfstream.h"
+#include "commodity.h"
+#include "annotate.h"
+#include "balance.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+namespace {
+
+ boost::optional<balance_t> py_value_0(const balance_t& balance) {
+ return balance.value(false, CURRENT_TIME());
+ }
+ boost::optional<balance_t> py_value_1(const balance_t& balance,
+ commodity_t& in_terms_of) {
+ return balance.value(false, CURRENT_TIME(), in_terms_of);
+ }
+ boost::optional<balance_t> py_value_2(const balance_t& balance,
+ commodity_t& in_terms_of,
+ datetime_t& moment) {
+ return balance.value(false, moment, in_terms_of);
+ }
+
+ boost::optional<amount_t>
+ py_commodity_amount_0(const balance_t& balance) {
+ return balance.commodity_amount();
+ }
+
+ boost::optional<amount_t>
+ py_commodity_amount_1(const balance_t& balance,
+ const boost::optional<const commodity_t&>& commodity) {
+ return balance.commodity_amount(commodity);
+ }
+
+ void py_print(balance_t& balance, object out) {
+ if (PyFile_Check(out.ptr())) {
+ pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr()));
+ balance.print(outstr);
+ } else {
+ PyErr_SetString(PyExc_IOError,
+ _("Argument to balance.print_(file) is not a file object"));
+ }
+ }
+
+ long balance_len(balance_t& bal) {
+ return bal.amounts.size();
+ }
+
+ amount_t balance_getitem(balance_t& bal, long i) {
+ long len = bal.amounts.size();
+
+ if (labs(i) >= len) {
+ PyErr_SetString(PyExc_IndexError, _("Index out of range"));
+ throw_error_already_set();
+ }
+
+ long x = i < 0 ? len + i : i;
+ balance_t::amounts_map::iterator elem = bal.amounts.begin();
+ while (--x >= 0)
+ elem++;
+
+ return (*elem).second;
+ }
+
+ balance_t py_strip_annotations_0(balance_t& balance) {
+ return balance.strip_annotations(keep_details_t());
+ }
+ balance_t py_strip_annotations_1(balance_t& balance, const keep_details_t& keep) {
+ return balance.strip_annotations(keep);
+ }
+
+ PyObject * py_balance_unicode(balance_t& balance) {
+ return str_to_py_unicode(balance.to_string());
+ }
+
+} // unnamed namespace
+
+#define EXC_TRANSLATOR(type) \
+ void exc_translate_ ## type(const type& err) { \
+ PyErr_SetString(PyExc_ArithmeticError, err.what()); \
+ }
+
+EXC_TRANSLATOR(balance_error)
+
+void export_balance()
+{
+ class_< balance_t > ("Balance")
+ .def(init<balance_t>())
+ .def(init<amount_t>())
+ .def(init<long>())
+ .def(init<string>())
+
+ .def(self += self)
+ .def(self += other<amount_t>())
+ .def(self += long())
+ .def(self + self)
+ .def(self + other<amount_t>())
+ .def(self + long())
+ .def(self -= self)
+ .def(self -= other<amount_t>())
+ .def(self -= long())
+ .def(self - self)
+ .def(self - other<amount_t>())
+ .def(self - long())
+ .def(self *= other<amount_t>())
+ .def(self *= long())
+ .def(self * other<amount_t>())
+ .def(self * long())
+ .def(self /= other<amount_t>())
+ .def(self /= long())
+ .def(self / other<amount_t>())
+ .def(self / long())
+ .def(- self)
+
+ .def(self == self)
+ .def(self == other<amount_t>())
+ .def(self == long())
+ .def(self != self)
+ .def(self != other<amount_t>())
+ .def(self != long())
+ .def(! self)
+
+ .def("__str__", &balance_t::to_string)
+ .def("to_string", &balance_t::to_string)
+ .def("__unicode__", py_balance_unicode)
+
+ .def("negated", &balance_t::negated)
+ .def("in_place_negate", &balance_t::in_place_negate,
+ return_internal_reference<>())
+ .def(- self)
+
+ .def("abs", &balance_t::abs)
+ .def("__abs__", &balance_t::abs)
+
+ .def("__len__", balance_len)
+ .def("__getitem__", balance_getitem)
+
+ .def("rounded", &balance_t::rounded)
+ .def("in_place_round", &balance_t::in_place_round,
+ return_internal_reference<>())
+
+ .def("truncated", &balance_t::truncated)
+ .def("in_place_truncate", &balance_t::in_place_truncate,
+ return_internal_reference<>())
+
+ .def("floored", &balance_t::floored)
+ .def("in_place_floor", &balance_t::in_place_floor,
+ return_internal_reference<>())
+
+ .def("unrounded", &balance_t::unrounded)
+ .def("in_place_unround", &balance_t::in_place_unround,
+ return_internal_reference<>())
+
+ .def("reduced", &balance_t::reduced)
+ .def("in_place_reduce", &balance_t::in_place_reduce,
+ return_internal_reference<>())
+
+ .def("unreduced", &balance_t::unreduced)
+ .def("in_place_unreduce", &balance_t::in_place_unreduce,
+ return_internal_reference<>())
+
+ .def("value", py_value_0)
+ .def("value", py_value_1, args("in_terms_of"))
+ .def("value", py_value_2, args("in_terms_of", "moment"))
+
+ .def("price", &balance_t::price)
+
+ .def("__nonzero__", &balance_t::is_nonzero)
+ .def("is_nonzero", &balance_t::is_nonzero)
+ .def("is_zero", &balance_t::is_zero)
+ .def("is_realzero", &balance_t::is_realzero)
+
+ .def("is_empty", &balance_t::is_empty)
+ .def("single_amount", &balance_t::single_amount)
+
+ .def("to_amount", &balance_t::to_amount)
+
+ .def("commodity_count", &balance_t::commodity_count)
+ .def("commodity_amount", py_commodity_amount_0)
+ .def("commodity_amount", py_commodity_amount_1)
+
+ .def("number", &balance_t::number)
+
+ .def("strip_annotations", py_strip_annotations_0)
+ .def("strip_annotations", py_strip_annotations_1)
+
+ .def("valid", &balance_t::valid)
+ ;
+
+ register_optional_to_python<balance_t>();
+
+ implicitly_convertible<long, balance_t>();
+ implicitly_convertible<string, balance_t>();
+ implicitly_convertible<amount_t, balance_t>();
+
+#define EXC_TRANSLATE(type) \
+ register_exception_translator<type>(&exc_translate_ ## type);
+
+ EXC_TRANSLATE(balance_error);
+}
+
+} // namespace ledger
diff --git a/src/py_commodity.cc b/src/py_commodity.cc
new file mode 100644
index 00000000..984be5f0
--- /dev/null
+++ b/src/py_commodity.cc
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "pyutils.h"
+#include "commodity.h"
+#include "annotate.h"
+#include "pool.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+namespace {
+
+ commodity_t * py_create_1(commodity_pool_t& pool,
+ const string& symbol)
+ {
+ return pool.create(symbol);
+ }
+ commodity_t * py_create_2(commodity_pool_t& pool,
+ const string& symbol,
+ const annotation_t& details)
+ {
+ return pool.create(symbol, details);
+ }
+
+ commodity_t * py_find_or_create_1(commodity_pool_t& pool,
+ const string& symbol)
+ {
+ return pool.find_or_create(symbol);
+ }
+ commodity_t * py_find_or_create_2(commodity_pool_t& pool,
+ const string& symbol,
+ const annotation_t& details)
+ {
+ return pool.find_or_create(symbol, details);
+ }
+
+ commodity_t * py_find_1(commodity_pool_t& pool,
+ const string& name)
+ {
+ return pool.find(name);
+ }
+
+ commodity_t * py_find_2(commodity_pool_t& pool,
+ const string& symbol,
+ const annotation_t& details)
+ {
+ return pool.find(symbol, details);
+ }
+
+ // Exchange one commodity for another, while recording the factored price.
+
+ void py_exchange_2(commodity_pool_t& pool,
+ commodity_t& commodity,
+ const amount_t& per_unit_cost)
+ {
+ pool.exchange(commodity, per_unit_cost, CURRENT_TIME());
+ }
+ void py_exchange_3(commodity_pool_t& pool,
+ commodity_t& commodity,
+ const amount_t& per_unit_cost,
+ const datetime_t& moment)
+ {
+ pool.exchange(commodity, per_unit_cost, moment);
+ }
+
+ cost_breakdown_t py_exchange_5(commodity_pool_t& pool,
+ const amount_t& amount,
+ const amount_t& cost,
+ const bool is_per_unit,
+ const boost::optional<datetime_t>& moment,
+ const boost::optional<string>& tag)
+ {
+ return pool.exchange(amount, cost, is_per_unit, moment, tag);
+ }
+
+ commodity_t * py_pool_getitem(commodity_pool_t& pool, const string& symbol)
+ {
+ commodity_pool_t::commodities_map::iterator i =
+ pool.commodities.find(symbol);
+ if (i == pool.commodities.end()) {
+ PyErr_SetString(PyExc_ValueError,
+ (string("Could not find commodity ") + symbol).c_str());
+ throw boost::python::error_already_set();
+ }
+ return (*i).second;
+ }
+
+ python::list py_pool_keys(commodity_pool_t& pool) {
+ python::list keys;
+ BOOST_REVERSE_FOREACH
+ (const commodity_pool_t::commodities_map::value_type& pair,
+ pool.commodities) {
+ keys.insert(0, pair.first);
+ }
+ return keys;
+ }
+
+ bool py_pool_contains(commodity_pool_t& pool, const string& symbol) {
+ return pool.commodities.find(symbol) != pool.commodities.end();
+ }
+
+ commodity_pool_t::commodities_map::iterator
+ py_pool_commodities_begin(commodity_pool_t& pool) {
+ return pool.commodities.begin();
+ }
+ commodity_pool_t::commodities_map::iterator
+ py_pool_commodities_end(commodity_pool_t& pool) {
+ return pool.commodities.end();
+ }
+
+ typedef transform_iterator
+ <function<string(commodity_pool_t::commodities_map::value_type&)>,
+ commodity_pool_t::commodities_map::iterator>
+ commodities_map_firsts_iterator;
+ commodities_map_firsts_iterator
+
+ py_pool_commodities_keys_begin(commodity_pool_t& pool) {
+ return make_transform_iterator
+ (pool.commodities.begin(),
+ bind(&commodity_pool_t::commodities_map::value_type::first, _1));
+ }
+ commodities_map_firsts_iterator
+ py_pool_commodities_keys_end(commodity_pool_t& pool) {
+ return make_transform_iterator
+ (pool.commodities.end(),
+ bind(&commodity_pool_t::commodities_map::value_type::first, _1));
+ }
+
+ typedef transform_iterator
+ <function<commodity_t *(commodity_pool_t::commodities_map::value_type&)>,
+ commodity_pool_t::commodities_map::iterator>
+ commodities_map_seconds_iterator;
+
+ commodities_map_seconds_iterator
+ py_pool_commodities_values_begin(commodity_pool_t& pool) {
+ return make_transform_iterator
+ (pool.commodities.begin(),
+ bind(&commodity_pool_t::commodities_map::value_type::second, _1));
+ }
+ commodities_map_seconds_iterator
+ py_pool_commodities_values_end(commodity_pool_t& pool) {
+ return make_transform_iterator
+ (pool.commodities.end(),
+ bind(&commodity_pool_t::commodities_map::value_type::second, _1));
+ }
+
+ void py_add_price_2(commodity_t& commodity,
+ const datetime_t& date, const amount_t& price) {
+ commodity.add_price(date, price);
+ }
+
+ void py_add_price_3(commodity_t& commodity, const datetime_t& date,
+ const amount_t& price, const bool reflexive) {
+ commodity.add_price(date, price, reflexive);
+ }
+
+ bool py_keep_all_0(keep_details_t& details) {
+ return details.keep_all();
+ }
+ bool py_keep_all_1(keep_details_t& details, const commodity_t& comm) {
+ return details.keep_all(comm);
+ }
+
+ bool py_keep_any_0(keep_details_t& details) {
+ return details.keep_any();
+ }
+ bool py_keep_any_1(keep_details_t& details, const commodity_t& comm) {
+ return details.keep_any(comm);
+ }
+
+ commodity_t& py_commodity_referent(commodity_t& comm) {
+ return comm.referent();
+ }
+ commodity_t& py_annotated_commodity_referent(annotated_commodity_t& comm) {
+ return comm.referent();
+ }
+
+ commodity_t& py_strip_annotations_0(commodity_t& comm) {
+ return comm.strip_annotations(keep_details_t());
+ }
+ commodity_t& py_strip_annotations_1(commodity_t& comm,
+ const keep_details_t& keep) {
+ return comm.strip_annotations(keep);
+ }
+
+ commodity_t& py_strip_ann_annotations_0(annotated_commodity_t& comm) {
+ return comm.strip_annotations(keep_details_t());
+ }
+ commodity_t& py_strip_ann_annotations_1(annotated_commodity_t& comm,
+ const keep_details_t& keep) {
+ return comm.strip_annotations(keep);
+ }
+
+ boost::optional<amount_t> py_price(annotation_t& ann) {
+ return ann.price;
+ }
+ boost::optional<amount_t> py_set_price(annotation_t& ann,
+ const boost::optional<amount_t>& price) {
+ return ann.price = price;
+ }
+
+ PyObject * py_commodity_unicode(commodity_t& commodity) {
+ return str_to_py_unicode(commodity.symbol());
+ }
+
+} // unnamed namespace
+
+void export_commodity()
+{
+ class_< commodity_pool_t, shared_ptr<commodity_pool_t>,
+ boost::noncopyable > ("CommodityPool", no_init)
+ .add_property("null_commodity",
+ make_getter(&commodity_pool_t::null_commodity,
+ return_internal_reference<>()))
+ .add_property("default_commodity",
+ make_getter(&commodity_pool_t::default_commodity,
+ return_internal_reference<>()),
+ make_setter(&commodity_pool_t::default_commodity,
+ with_custodian_and_ward<1, 2>()))
+
+ .add_property("keep_base",
+ make_getter(&commodity_pool_t::keep_base),
+ make_setter(&commodity_pool_t::keep_base))
+ .add_property("price_db",
+ make_getter(&commodity_pool_t::price_db),
+ make_setter(&commodity_pool_t::price_db))
+ .add_property("quote_leeway",
+ make_getter(&commodity_pool_t::quote_leeway),
+ make_setter(&commodity_pool_t::quote_leeway))
+ .add_property("get_quotes",
+ make_getter(&commodity_pool_t::get_quotes),
+ make_setter(&commodity_pool_t::get_quotes))
+ .add_property("get_commodity_quote",
+ make_getter(&commodity_pool_t::get_commodity_quote),
+ make_setter(&commodity_pool_t::get_commodity_quote))
+
+ .def("make_qualified_name", &commodity_pool_t::make_qualified_name)
+
+ .def("create", py_create_1,
+ return_value_policy<reference_existing_object>())
+ .def("create", py_create_2,
+ return_value_policy<reference_existing_object>())
+
+ .def("find_or_create", py_find_or_create_1,
+ return_value_policy<reference_existing_object>())
+ .def("find_or_create", py_find_or_create_2,
+ return_value_policy<reference_existing_object>())
+
+ .def("find", py_find_1, return_value_policy<reference_existing_object>())
+ .def("find", py_find_2, return_value_policy<reference_existing_object>())
+
+ .def("exchange", py_exchange_2, with_custodian_and_ward<1, 2>())
+ .def("exchange", py_exchange_3, with_custodian_and_ward<1, 2>())
+ .def("exchange", py_exchange_5)
+
+ .def("parse_price_directive", &commodity_pool_t::parse_price_directive)
+ .def("parse_price_expression", &commodity_pool_t::parse_price_expression,
+ return_value_policy<reference_existing_object>())
+
+ .def("__getitem__", py_pool_getitem,
+ return_value_policy<reference_existing_object>())
+ .def("keys", py_pool_keys)
+ .def("has_key", py_pool_contains)
+ .def("__contains__", py_pool_contains)
+ .def("__iter__", range<return_value_policy<reference_existing_object> >
+ (py_pool_commodities_begin, py_pool_commodities_end))
+ .def("iteritems", range<return_value_policy<reference_existing_object> >
+ (py_pool_commodities_begin, py_pool_commodities_end))
+ .def("iterkeys", range<>(py_pool_commodities_keys_begin,
+ py_pool_commodities_keys_end))
+ .def("itervalues", range<return_value_policy<reference_existing_object> >
+ (py_pool_commodities_values_begin, py_pool_commodities_values_end))
+ ;
+
+ map_value_type_converter<commodity_pool_t::commodities_map>();
+
+ scope().attr("commodities") = commodity_pool_t::current_pool;
+
+ scope().attr("COMMODITY_STYLE_DEFAULTS") = COMMODITY_STYLE_DEFAULTS;
+ scope().attr("COMMODITY_STYLE_SUFFIXED") = COMMODITY_STYLE_SUFFIXED;
+ scope().attr("COMMODITY_STYLE_SEPARATED") = COMMODITY_STYLE_SEPARATED;
+ scope().attr("COMMODITY_STYLE_EUROPEAN") = COMMODITY_STYLE_EUROPEAN;
+ scope().attr("COMMODITY_STYLE_THOUSANDS") = COMMODITY_STYLE_THOUSANDS;
+ scope().attr("COMMODITY_NOMARKET") = COMMODITY_NOMARKET;
+ scope().attr("COMMODITY_BUILTIN") = COMMODITY_BUILTIN;
+ scope().attr("COMMODITY_WALKED") = COMMODITY_WALKED;
+ scope().attr("COMMODITY_KNOWN") = COMMODITY_KNOWN;
+ scope().attr("COMMODITY_PRIMARY") = COMMODITY_PRIMARY;
+
+ class_< commodity_t, boost::noncopyable > ("Commodity", no_init)
+#if 1
+ .add_property("flags",
+ &supports_flags<uint_least16_t>::flags,
+ &supports_flags<uint_least16_t>::set_flags)
+ .def("has_flags", &delegates_flags<uint_least16_t>::has_flags)
+ .def("clear_flags", &delegates_flags<uint_least16_t>::clear_flags)
+ .def("add_flags", &delegates_flags<uint_least16_t>::add_flags)
+ .def("drop_flags", &delegates_flags<uint_least16_t>::drop_flags)
+#endif
+
+ .add_static_property("european_by_default",
+ make_getter(&commodity_t::european_by_default),
+ make_setter(&commodity_t::european_by_default))
+
+ .def("__str__", &commodity_t::symbol)
+ .def("__unicode__", py_commodity_unicode)
+ .def("__nonzero__", &commodity_t::operator bool)
+
+ .def(self == self)
+
+ .def("symbol_needs_quotes", &commodity_t::symbol_needs_quotes)
+ .staticmethod("symbol_needs_quotes")
+
+ .add_property("referent",
+ make_function(py_commodity_referent,
+ return_value_policy<reference_existing_object>()))
+
+ .def("has_annotation", &commodity_t::has_annotation)
+ .def("strip_annotations", py_strip_annotations_0,
+ return_value_policy<reference_existing_object>())
+ .def("strip_annotations", py_strip_annotations_1,
+ return_value_policy<reference_existing_object>())
+ .def("write_annotations", &commodity_t::write_annotations)
+
+ .def("pool", &commodity_t::pool,
+ return_value_policy<reference_existing_object>())
+
+ .add_property("base_symbol", &commodity_t::base_symbol)
+ .add_property("symbol", &commodity_t::symbol)
+ .add_property("mapping_key", &commodity_t::mapping_key)
+
+ .add_property("name", &commodity_t::name, &commodity_t::set_name)
+ .add_property("note", &commodity_t::note, &commodity_t::set_note)
+ .add_property("precision", &commodity_t::precision,
+ &commodity_t::set_precision)
+ .add_property("smaller", &commodity_t::smaller, &commodity_t::set_smaller)
+ .add_property("larger", &commodity_t::larger, &commodity_t::set_larger)
+
+ .def("add_price", py_add_price_2)
+ .def("add_price", py_add_price_3)
+ .def("remove_price", &commodity_t::remove_price,
+ with_custodian_and_ward<1, 3>())
+ .def("find_price", &commodity_t::find_price)
+ .def("check_for_updated_price", &commodity_t::check_for_updated_price)
+
+ .def("valid", &commodity_t::valid)
+ ;
+
+ class_< annotation_t > ("Annotation", no_init)
+#if 1
+ .add_property("flags", &supports_flags<>::flags,
+ &supports_flags<>::set_flags)
+ .def("has_flags", &supports_flags<>::has_flags)
+ .def("clear_flags", &supports_flags<>::clear_flags)
+ .def("add_flags", &supports_flags<>::add_flags)
+ .def("drop_flags", &supports_flags<>::drop_flags)
+#endif
+
+ .add_property("price", py_price, py_set_price)
+ .add_property("date",
+ make_getter(&annotation_t::date),
+ make_setter(&annotation_t::date))
+ .add_property("tag",
+ make_getter(&annotation_t::tag),
+ make_setter(&annotation_t::tag))
+
+ .def("__nonzero__", &annotation_t::operator bool)
+
+ .def(self == self)
+
+ .def("valid", &annotation_t::valid)
+ ;
+
+ class_< keep_details_t > ("KeepDetails")
+ .def(init<bool, bool, bool, bool>())
+
+ .add_property("keep_price",
+ make_getter(&keep_details_t::keep_price),
+ make_setter(&keep_details_t::keep_price))
+ .add_property("keep_date",
+ make_getter(&keep_details_t::keep_date),
+ make_setter(&keep_details_t::keep_date))
+ .add_property("keep_tag",
+ make_getter(&keep_details_t::keep_tag),
+ make_setter(&keep_details_t::keep_tag))
+ .add_property("only_actuals",
+ make_getter(&keep_details_t::only_actuals),
+ make_setter(&keep_details_t::only_actuals))
+
+ .def("keep_all", py_keep_all_0)
+ .def("keep_all", py_keep_all_1)
+ .def("keep_any", py_keep_any_0)
+ .def("keep_any", py_keep_any_1)
+ ;
+
+ class_< annotated_commodity_t, bases<commodity_t>,
+ annotated_commodity_t, boost::noncopyable >
+ ("AnnotatedCommodity", no_init)
+ .add_property("details",
+ make_getter(&annotated_commodity_t::details),
+ make_setter(&annotated_commodity_t::details))
+
+ .def(self == self)
+ .def(self == other<commodity_t>())
+
+ .add_property("referent",
+ make_function(py_annotated_commodity_referent,
+ return_value_policy<reference_existing_object>()))
+
+ .def("strip_annotations", py_strip_ann_annotations_0,
+ return_value_policy<reference_existing_object>())
+ .def("strip_annotations", py_strip_ann_annotations_1,
+ return_value_policy<reference_existing_object>())
+ .def("write_annotations", &annotated_commodity_t::write_annotations)
+ ;
+}
+
+} // namespace ledger
diff --git a/src/py_expr.cc b/src/py_expr.cc
new file mode 100644
index 00000000..cad2c0fa
--- /dev/null
+++ b/src/py_expr.cc
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+namespace {
+ value_t py_expr_call(expr_t& expr)
+ {
+ return expr.calc();
+ }
+}
+
+void export_expr()
+{
+ class_< expr_t > ("Expr")
+ .def(init<string>())
+
+ .def("__nonzero__", &expr_t::operator bool)
+ .def("text", &expr_t::text)
+ .def("set_text", &expr_t::set_text)
+
+ //.def("parse", &expr_t::parse)
+
+ .def("__call__", py_expr_call)
+ .def("compile", &expr_t::compile)
+ //.def("calc", &expr_t::calc)
+
+ .def("is_constant", &expr_t::is_constant)
+
+ //.def("constant_value", &expr_t::constant_value)
+ ;
+}
+
+} // namespace ledger
diff --git a/src/py_format.cc b/src/py_format.cc
new file mode 100644
index 00000000..d4825b42
--- /dev/null
+++ b/src/py_format.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+#define EXC_TRANSLATOR(type) \
+ void exc_translate_ ## type(const type& err) { \
+ PyErr_SetString(PyExc_ArithmeticError, err.what()); \
+ }
+
+//EXC_TRANSLATOR(format_error)
+
+void export_format()
+{
+#if 0
+ class_< format_t > ("Format")
+ ;
+#endif
+
+ //register_optional_to_python<amount_t>();
+
+ //implicitly_convertible<string, amount_t>();
+
+#define EXC_TRANSLATE(type) \
+ register_exception_translator<type>(&exc_translate_ ## type);
+
+ //EXC_TRANSLATE(format_error);
+}
+
+} // namespace ledger
diff --git a/src/py_item.cc b/src/py_item.cc
new file mode 100644
index 00000000..8a6e495a
--- /dev/null
+++ b/src/py_item.cc
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "scope.h"
+#include "mask.h"
+#include "item.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+namespace {
+
+ bool py_has_tag_1s(item_t& item, const string& tag) {
+ return item.has_tag(tag);
+ }
+ bool py_has_tag_1m(item_t& item, const mask_t& tag_mask) {
+ return item.has_tag(tag_mask);
+ }
+ bool py_has_tag_2m(item_t& item, const mask_t& tag_mask,
+ const boost::optional<mask_t>& value_mask) {
+ return item.has_tag(tag_mask, value_mask);
+ }
+
+ boost::optional<string> py_get_tag_1s(item_t& item, const string& tag) {
+ return item.get_tag(tag);
+ }
+ boost::optional<string> py_get_tag_1m(item_t& item, const mask_t& tag_mask) {
+ return item.get_tag(tag_mask);
+ }
+ boost::optional<string> py_get_tag_2m(item_t& item, const mask_t& tag_mask,
+ const boost::optional<mask_t>& value_mask) {
+ return item.get_tag(tag_mask, value_mask);
+ }
+
+} // unnamed namespace
+
+#define EXC_TRANSLATOR(type) \
+ void exc_translate_ ## type(const type& err) { \
+ PyErr_SetString(PyExc_ArithmeticError, err.what()); \
+ }
+
+//EXC_TRANSLATOR(item_error)
+
+void export_item()
+{
+ class_< position_t > ("Position")
+ .add_property("pathname",
+ make_getter(&position_t::pathname),
+ make_setter(&position_t::pathname))
+ .add_property("beg_pos",
+ make_getter(&position_t::beg_pos),
+ make_setter(&position_t::beg_pos))
+ .add_property("beg_line",
+ make_getter(&position_t::beg_line),
+ make_setter(&position_t::beg_line))
+ .add_property("end_pos",
+ make_getter(&position_t::end_pos),
+ make_setter(&position_t::end_pos))
+ .add_property("end_line",
+ make_getter(&position_t::end_line),
+ make_setter(&position_t::end_line))
+ ;
+
+ scope().attr("ITEM_NORMAL") = ITEM_NORMAL;
+ scope().attr("ITEM_GENERATED") = ITEM_GENERATED;
+ scope().attr("ITEM_TEMP") = ITEM_TEMP;
+
+ enum_< item_t::state_t > ("State")
+ .value("Uncleared", item_t::UNCLEARED)
+ .value("Cleared", item_t::CLEARED)
+ .value("Pending", item_t::PENDING)
+ ;
+
+#if 0
+ class_< item_t, bases<scope_t> > ("JournalItem", init<uint_least8_t>())
+#else
+ class_< item_t > ("JournalItem", init<uint_least8_t>())
+#endif
+#if 1
+ .add_property("flags", &supports_flags<>::flags,
+ &supports_flags<>::set_flags)
+ .def("has_flags", &supports_flags<>::has_flags)
+ .def("clear_flags", &supports_flags<>::clear_flags)
+ .def("add_flags", &supports_flags<>::add_flags)
+ .def("drop_flags", &supports_flags<>::drop_flags)
+#endif
+
+ .add_property("note",
+ make_getter(&item_t::note),
+ make_setter(&item_t::note))
+ .add_property("pos",
+ make_getter(&item_t::pos),
+ make_setter(&item_t::pos))
+ .add_property("metadata",
+ make_getter(&item_t::metadata),
+ make_setter(&item_t::metadata))
+
+ .def("copy_details", &item_t::copy_details)
+
+ .def(self == self)
+ .def(self != self)
+
+ .def("has_tag", py_has_tag_1s)
+ .def("has_tag", py_has_tag_1m)
+ .def("has_tag", py_has_tag_2m)
+ .def("get_tag", py_get_tag_1s)
+ .def("get_tag", py_get_tag_1m)
+ .def("get_tag", py_get_tag_2m)
+ .def("tag", py_get_tag_1s)
+ .def("tag", py_get_tag_1m)
+ .def("tag", py_get_tag_2m)
+
+ .def("set_tag", &item_t::set_tag)
+
+ .def("parse_tags", &item_t::parse_tags)
+ .def("append_note", &item_t::append_note)
+
+ .add_static_property("use_effective_date",
+ make_getter(&item_t::use_effective_date),
+ make_setter(&item_t::use_effective_date))
+
+ .add_property("date", &item_t::date, make_setter(&item_t::_date))
+ .add_property("effective_date", &item_t::effective_date,
+ make_setter(&item_t::_date_eff))
+
+ .add_property("state", &item_t::state, &item_t::set_state)
+
+ .def("lookup", &item_t::lookup)
+
+ .def("valid", &item_t::valid)
+ ;
+}
+
+} // namespace ledger
diff --git a/src/py_journal.cc b/src/py_journal.cc
new file mode 100644
index 00000000..5be9cbe1
--- /dev/null
+++ b/src/py_journal.cc
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "pyutils.h"
+#include "journal.h"
+#include "xact.h"
+#include "post.h"
+#include "chain.h"
+#include "filters.h"
+#include "iterators.h"
+#include "scope.h"
+#include "report.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+namespace {
+
+ account_t& py_account_master(journal_t& journal) {
+ return *journal.master;
+ }
+
+ long xacts_len(journal_t& journal)
+ {
+ return journal.xacts.size();
+ }
+
+ xact_t& xacts_getitem(journal_t& journal, long i)
+ {
+ static long last_index = 0;
+ static journal_t * last_journal = NULL;
+ static xacts_list::iterator elem;
+
+ long len = journal.xacts.size();
+
+ if (labs(i) >= len) {
+ PyErr_SetString(PyExc_IndexError, _("Index out of range"));
+ throw_error_already_set();
+ }
+
+ if (&journal == last_journal && i == last_index + 1) {
+ last_index = i;
+ return **++elem;
+ }
+
+ long x = i < 0 ? len + i : i;
+ elem = journal.xacts.begin();
+ while (--x >= 0)
+ elem++;
+
+ last_journal = &journal;
+ last_index = i;
+
+ return **elem;
+ }
+
+ long accounts_len(account_t& account)
+ {
+ return account.accounts.size();
+ }
+
+ account_t& accounts_getitem(account_t& account, long i)
+ {
+ static long last_index = 0;
+ static account_t * last_account = NULL;
+ static accounts_map::iterator elem;
+
+ long len = account.accounts.size();
+
+ if (labs(i) >= len) {
+ PyErr_SetString(PyExc_IndexError, _("Index out of range"));
+ throw_error_already_set();
+ }
+
+ if (&account == last_account && i == last_index + 1) {
+ last_index = i;
+ return *(*++elem).second;
+ }
+
+ long x = i < 0 ? len + i : i;
+ elem = account.accounts.begin();
+ while (--x >= 0)
+ elem++;
+
+ last_account = &account;
+ last_index = i;
+
+ return *(*elem).second;
+ }
+
+ account_t * py_find_account_1(journal_t& journal, const string& name)
+ {
+ return journal.find_account(name);
+ }
+
+ account_t * py_find_account_2(journal_t& journal, const string& name,
+ const bool auto_create)
+ {
+ return journal.find_account(name, auto_create);
+ }
+
+ std::size_t py_read(journal_t& journal, const string& pathname)
+ {
+ return journal.read(pathname);
+ }
+
+ struct collector_wrapper
+ {
+ journal_t& journal;
+ report_t report;
+ collect_posts * posts_collector;
+ post_handler_ptr chain;
+
+ collector_wrapper(journal_t& _journal, report_t& base)
+ : journal(_journal), report(base),
+ posts_collector(new collect_posts) {}
+ ~collector_wrapper() {
+ journal.clear_xdata();
+ }
+
+ std::size_t length() const {
+ return posts_collector->length();
+ }
+
+ std::vector<post_t *>::iterator begin() {
+ return posts_collector->begin();
+ }
+ std::vector<post_t *>::iterator end() {
+ return posts_collector->end();
+ }
+ };
+
+ shared_ptr<collector_wrapper>
+ py_collect(journal_t& journal, const string& query)
+ {
+ if (journal.has_xdata()) {
+ PyErr_SetString(PyExc_RuntimeError,
+ _("Cannot have multiple journal collections open at once"));
+ throw_error_already_set();
+ }
+
+ report_t& current_report(downcast<report_t>(*scope_t::default_scope));
+ shared_ptr<collector_wrapper> coll(new collector_wrapper(journal,
+ current_report));
+ std::auto_ptr<journal_t> save_journal
+ (current_report.session.journal.release());
+ current_report.session.journal.reset(&journal);
+
+ try {
+ strings_list remaining =
+ process_arguments(split_arguments(query.c_str()), coll->report);
+ coll->report.normalize_options("register");
+
+ value_t args;
+ foreach (const string& arg, remaining)
+ args.push_back(string_value(arg));
+ coll->report.parse_query_args(args, "@Journal.collect");
+
+ journal_posts_iterator walker(coll->journal);
+ coll->chain =
+ chain_post_handlers(coll->report,
+ post_handler_ptr(coll->posts_collector));
+ pass_down_posts(coll->chain, walker);
+ }
+ catch (...) {
+ current_report.session.journal.release();
+ current_report.session.journal.reset(save_journal.release());
+ throw;
+ }
+ current_report.session.journal.release();
+ current_report.session.journal.reset(save_journal.release());
+
+ return coll;
+ }
+
+ post_t * posts_getitem(collector_wrapper& collector, long i)
+ {
+ post_t * post = collector.posts_collector->posts[i];
+ std::cerr << typeid(post).name() << std::endl;
+ std::cerr << typeid(*post).name() << std::endl;
+ std::cerr << typeid(post->account).name() << std::endl;
+ std::cerr << typeid(*post->account).name() << std::endl;
+ return post;
+ }
+
+} // unnamed namespace
+
+void export_journal()
+{
+ class_< item_handler<post_t>, shared_ptr<item_handler<post_t> >,
+ boost::noncopyable >("PostHandler")
+ ;
+
+ class_< collect_posts, bases<item_handler<post_t> >,
+ shared_ptr<collect_posts>, boost::noncopyable >("PostCollector")
+ .def("__len__", &collect_posts::length)
+ .def("__iter__", range<return_internal_reference<1,
+ with_custodian_and_ward_postcall<1, 0> > >
+ (&collect_posts::begin, &collect_posts::end))
+ ;
+
+ class_< collector_wrapper, shared_ptr<collector_wrapper>,
+ boost::noncopyable >("PostCollectorWrapper", no_init)
+ .def("__len__", &collector_wrapper::length)
+ .def("__getitem__", posts_getitem, return_internal_reference<1,
+ with_custodian_and_ward_postcall<0, 1> >())
+ .def("__iter__", range<return_value_policy<reference_existing_object,
+ with_custodian_and_ward_postcall<0, 1> > >
+ (&collector_wrapper::begin, &collector_wrapper::end))
+ ;
+
+ class_< journal_t::fileinfo_t > ("FileInfo")
+ .def(init<path>())
+
+ .add_property("filename",
+ make_getter(&journal_t::fileinfo_t::filename),
+ make_setter(&journal_t::fileinfo_t::filename))
+ .add_property("size",
+ make_getter(&journal_t::fileinfo_t::size),
+ make_setter(&journal_t::fileinfo_t::size))
+ .add_property("modtime",
+ make_getter(&journal_t::fileinfo_t::modtime),
+ make_setter(&journal_t::fileinfo_t::modtime))
+ .add_property("from_stream",
+ make_getter(&journal_t::fileinfo_t::from_stream),
+ make_setter(&journal_t::fileinfo_t::from_stream))
+ ;
+
+ class_< journal_t, boost::noncopyable > ("Journal")
+ .def(init<path>())
+ .def(init<string>())
+
+ .add_property("master",
+ make_getter(&journal_t::master,
+ return_internal_reference<1,
+ with_custodian_and_ward_postcall<1, 0> >()))
+ .add_property("bucket",
+ make_getter(&journal_t::bucket,
+ return_internal_reference<1,
+ with_custodian_and_ward_postcall<1, 0> >()),
+ make_setter(&journal_t::bucket))
+ .add_property("was_loaded", make_getter(&journal_t::was_loaded))
+
+ .def("add_account", &journal_t::add_account)
+ .def("remove_account", &journal_t::remove_account)
+
+ .def("find_account", py_find_account_1,
+ return_internal_reference<1,
+ with_custodian_and_ward_postcall<0, 1> >())
+ .def("find_account", py_find_account_2,
+ return_internal_reference<1,
+ with_custodian_and_ward_postcall<0, 1> >())
+ .def("find_account_re", &journal_t::find_account_re,
+ return_internal_reference<1,
+ with_custodian_and_ward_postcall<0, 1> >())
+
+ .def("add_xact", &journal_t::add_xact)
+ .def("remove_xact", &journal_t::remove_xact)
+
+ .def("__len__", xacts_len)
+#if 0
+ .def("__getitem__", xacts_getitem,
+ return_internal_reference<1,
+ with_custodian_and_ward_postcall<0, 1> >())
+#endif
+
+ .def("__iter__", range<return_internal_reference<> >
+ (&journal_t::xacts_begin, &journal_t::xacts_end))
+ .def("xacts", range<return_internal_reference<> >
+ (&journal_t::xacts_begin, &journal_t::xacts_end))
+ .def("auto_xacts", range<return_internal_reference<> >
+ (&journal_t::auto_xacts_begin, &journal_t::auto_xacts_end))
+ .def("period_xacts", range<return_internal_reference<> >
+ (&journal_t::period_xacts_begin, &journal_t::period_xacts_end))
+ .def("sources", range<return_internal_reference<> >
+ (&journal_t::sources_begin, &journal_t::sources_end))
+
+ .def("read", py_read)
+
+ .def("has_xdata", &journal_t::has_xdata)
+ .def("clear_xdata", &journal_t::clear_xdata)
+
+ .def("collect", py_collect, with_custodian_and_ward_postcall<0, 1>())
+
+ .def("valid", &journal_t::valid)
+ ;
+}
+
+} // namespace ledger
diff --git a/src/py_post.cc b/src/py_post.cc
new file mode 100644
index 00000000..20cdba6b
--- /dev/null
+++ b/src/py_post.cc
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "post.h"
+#include "xact.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+namespace {
+
+ bool py_has_tag_1s(post_t& post, const string& tag) {
+ return post.has_tag(tag);
+ }
+ bool py_has_tag_1m(post_t& post, const mask_t& tag_mask) {
+ return post.has_tag(tag_mask);
+ }
+ bool py_has_tag_2m(post_t& post, const mask_t& tag_mask,
+ const boost::optional<mask_t>& value_mask) {
+ return post.has_tag(tag_mask, value_mask);
+ }
+
+ boost::optional<string> py_get_tag_1s(post_t& post, const string& tag) {
+ return post.get_tag(tag);
+ }
+ boost::optional<string> py_get_tag_1m(post_t& post, const mask_t& tag_mask) {
+ return post.get_tag(tag_mask);
+ }
+ boost::optional<string> py_get_tag_2m(post_t& post, const mask_t& tag_mask,
+ const boost::optional<mask_t>& value_mask) {
+ return post.get_tag(tag_mask, value_mask);
+ }
+
+ post_t::xdata_t& py_xdata(post_t& post) {
+ return post.xdata();
+ }
+
+ account_t * py_reported_account(post_t& post) {
+ return post.reported_account();
+ }
+
+} // unnamed namespace
+
+void export_post()
+{
+ scope().attr("POST_EXT_RECEIVED") = POST_EXT_RECEIVED;
+ scope().attr("POST_EXT_HANDLED") = POST_EXT_HANDLED;
+ scope().attr("POST_EXT_DISPLAYED") = POST_EXT_DISPLAYED;
+ scope().attr("POST_EXT_DIRECT_AMT") = POST_EXT_DIRECT_AMT;
+ scope().attr("POST_EXT_SORT_CALC") = POST_EXT_SORT_CALC;
+ scope().attr("POST_EXT_COMPOUND") = POST_EXT_COMPOUND;
+ scope().attr("POST_EXT_VISITED") = POST_EXT_VISITED;
+ scope().attr("POST_EXT_MATCHES") = POST_EXT_MATCHES;
+ scope().attr("POST_EXT_CONSIDERED") = POST_EXT_CONSIDERED;
+
+ class_< post_t::xdata_t > ("PostingXData")
+#if 1
+ .add_property("flags",
+ &supports_flags<uint_least16_t>::flags,
+ &supports_flags<uint_least16_t>::set_flags)
+ .def("has_flags", &supports_flags<uint_least16_t>::has_flags)
+ .def("clear_flags", &supports_flags<uint_least16_t>::clear_flags)
+ .def("add_flags", &supports_flags<uint_least16_t>::add_flags)
+ .def("drop_flags", &supports_flags<uint_least16_t>::drop_flags)
+#endif
+
+ .add_property("visited_value",
+ make_getter(&post_t::xdata_t::visited_value),
+ make_setter(&post_t::xdata_t::visited_value))
+ .add_property("compound_value",
+ make_getter(&post_t::xdata_t::compound_value),
+ make_setter(&post_t::xdata_t::compound_value))
+ .add_property("total",
+ make_getter(&post_t::xdata_t::total),
+ make_setter(&post_t::xdata_t::total))
+ .add_property("count",
+ make_getter(&post_t::xdata_t::count),
+ make_setter(&post_t::xdata_t::count))
+ .add_property("date",
+ make_getter(&post_t::xdata_t::date),
+ make_setter(&post_t::xdata_t::date))
+ .add_property("datetime",
+ make_getter(&post_t::xdata_t::datetime),
+ make_setter(&post_t::xdata_t::datetime))
+ .add_property("account",
+ make_getter(&post_t::xdata_t::account,
+ return_value_policy<reference_existing_object>()),
+ make_setter(&post_t::xdata_t::account,
+ with_custodian_and_ward<1, 2>()))
+ .add_property("sort_values",
+ make_getter(&post_t::xdata_t::sort_values),
+ make_setter(&post_t::xdata_t::sort_values))
+ ;
+
+ scope().attr("POST_VIRTUAL") = POST_VIRTUAL;
+ scope().attr("POST_MUST_BALANCE") = POST_MUST_BALANCE;
+ scope().attr("POST_CALCULATED") = POST_CALCULATED;
+ scope().attr("POST_COST_CALCULATED") = POST_COST_CALCULATED;
+
+ class_< post_t, bases<item_t> > ("Posting")
+ //.def(init<account_t *>())
+
+ .add_property("xact",
+ make_getter(&post_t::xact,
+ return_internal_reference<>()),
+ make_setter(&post_t::xact,
+ with_custodian_and_ward<1, 2>()))
+ .add_property("account",
+ make_getter(&post_t::account,
+ return_internal_reference<>()),
+ make_setter(&post_t::account,
+ with_custodian_and_ward<1, 2>()))
+ .add_property("amount",
+ make_getter(&post_t::amount),
+ make_setter(&post_t::amount))
+ .add_property("cost",
+ make_getter(&post_t::cost),
+ make_setter(&post_t::cost))
+ .add_property("assigned_amount",
+ make_getter(&post_t::assigned_amount),
+ make_setter(&post_t::assigned_amount))
+
+ .def("has_tag", py_has_tag_1s)
+ .def("has_tag", py_has_tag_1m)
+ .def("has_tag", py_has_tag_2m)
+ .def("get_tag", py_get_tag_1s)
+ .def("get_tag", py_get_tag_1m)
+ .def("get_tag", py_get_tag_2m)
+
+ .def("date", &post_t::date)
+ .def("effective_date", &post_t::effective_date)
+
+ .def("must_balance", &post_t::must_balance)
+
+ .def("lookup", &post_t::lookup)
+
+ .def("valid", &post_t::valid)
+
+ .def("has_xdata", &post_t::has_xdata)
+ .def("clear_xdata", &post_t::clear_xdata)
+ .def("xdata", py_xdata,
+ return_internal_reference<>())
+
+ .def("add_to_value", &post_t::add_to_value)
+ .def("set_reported_account", &post_t::set_reported_account)
+
+ .def("reported_account", py_reported_account,
+ return_internal_reference<>())
+ ;
+}
+
+} // namespace ledger
diff --git a/src/py_times.cc b/src/py_times.cc
new file mode 100644
index 00000000..a62bb9b6
--- /dev/null
+++ b/src/py_times.cc
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "pyutils.h"
+#include "times.h"
+
+// jww (2007-05-04): Convert time duration objects to PyDelta
+
+namespace ledger {
+
+using namespace boost::python;
+
+#define MY_PyDateTime_IMPORT \
+ PyDateTimeAPI = (PyDateTime_CAPI*) \
+ PyCObject_Import(const_cast<char *>("datetime"), \
+ const_cast<char *>("datetime_CAPI"))
+
+struct date_to_python
+{
+ static PyObject* convert(const date_t& dte)
+ {
+ MY_PyDateTime_IMPORT;
+ return PyDate_FromDate(dte.year(), dte.month(), dte.day());
+ }
+};
+
+struct date_from_python
+{
+ static void* convertible(PyObject* obj_ptr)
+ {
+ MY_PyDateTime_IMPORT;
+ if (PyDate_Check(obj_ptr)) return obj_ptr;
+ return 0;
+ }
+
+ static void construct(PyObject * obj_ptr,
+ converter::rvalue_from_python_stage1_data * data)
+ {
+ MY_PyDateTime_IMPORT;
+
+ int year = PyDateTime_GET_YEAR(obj_ptr);
+ date::year_type y = gregorian::greg_year(static_cast<unsigned short>(year));
+ date::month_type m =
+ static_cast<date::month_type>(PyDateTime_GET_MONTH(obj_ptr));
+ date::day_type d =
+ static_cast<date::day_type>(PyDateTime_GET_DAY(obj_ptr));
+
+ date_t * dte = new date_t(y, m, d);
+
+ data->convertible = (void *) dte;
+ }
+};
+
+typedef register_python_conversion<date_t, date_to_python, date_from_python>
+ date_python_conversion;
+
+
+struct datetime_to_python
+{
+ static PyObject* convert(const datetime_t& moment)
+ {
+ MY_PyDateTime_IMPORT;
+
+ date_t dte = moment.date();
+ datetime_t::time_duration_type tod = moment.time_of_day();
+
+ return PyDateTime_FromDateAndTime
+ (static_cast<int>(dte.year()), static_cast<int>(dte.month()),
+ static_cast<int>(dte.day()), static_cast<int>(tod.hours()),
+ static_cast<int>(tod.minutes()), static_cast<int>(tod.seconds()),
+ static_cast<int>(tod.total_microseconds() % 1000000));
+ }
+};
+
+struct datetime_from_python
+{
+ static void* convertible(PyObject* obj_ptr)
+ {
+ MY_PyDateTime_IMPORT;
+ if(PyDateTime_Check(obj_ptr)) return obj_ptr;
+ return 0;
+ }
+
+ static void construct(PyObject * obj_ptr,
+ converter::rvalue_from_python_stage1_data * data)
+ {
+ MY_PyDateTime_IMPORT;
+
+ int year = PyDateTime_GET_YEAR(obj_ptr);
+ date::year_type y = gregorian::greg_year(static_cast<unsigned short>(year));
+ date::month_type m =
+ static_cast<date::month_type>(PyDateTime_GET_MONTH(obj_ptr));
+ date::day_type d =
+ static_cast<date::day_type>(PyDateTime_GET_DAY(obj_ptr));
+
+ datetime_t::time_duration_type::hour_type h =
+ static_cast<datetime_t::time_duration_type::hour_type>
+ (PyDateTime_DATE_GET_HOUR(obj_ptr));
+ datetime_t::time_duration_type::min_type min =
+ static_cast<datetime_t::time_duration_type::min_type>
+ (PyDateTime_DATE_GET_MINUTE(obj_ptr));
+ datetime_t::time_duration_type::sec_type s =
+ static_cast<datetime_t::time_duration_type::sec_type>
+ (PyDateTime_DATE_GET_SECOND(obj_ptr));
+ datetime_t::time_duration_type::fractional_seconds_type ms =
+ static_cast<datetime_t::time_duration_type::fractional_seconds_type>
+ (PyDateTime_DATE_GET_MICROSECOND(obj_ptr)) * 1000000;
+
+ datetime_t * moment
+ = new datetime_t(date_t(y, m, d),
+ datetime_t::time_duration_type(h, min, s, ms));
+
+ data->convertible = (void *) moment;
+ }
+};
+
+typedef register_python_conversion<datetime_t,
+ datetime_to_python, datetime_from_python>
+ datetime_python_conversion;
+
+
+/* Convert time_duration to/from python */
+struct duration_to_python
+{
+ static int get_usecs(boost::posix_time::time_duration const& d)
+ {
+ static int64_t resolution =
+ boost::posix_time::time_duration::ticks_per_second();
+ int64_t fracsecs = d.fractional_seconds();
+ if (resolution > 1000000)
+ return static_cast<int>(fracsecs / (resolution / 1000000));
+ else
+ return static_cast<int>(fracsecs * (1000000 / resolution));
+ }
+
+ static PyObject * convert(posix_time::time_duration d)
+ {
+ int days = d.hours() / 24;
+ if (days < 0)
+ days --;
+ int seconds = d.total_seconds() - days*(24*3600);
+ int usecs = get_usecs(d);
+ if (days < 0)
+ usecs = 1000000-1 - usecs;
+ return PyDelta_FromDSU(days, seconds, usecs);
+ }
+};
+
+/* Should support the negative values, but not the special boost time
+ durations */
+struct duration_from_python
+{
+ static void* convertible(PyObject * obj_ptr)
+ {
+ if ( ! PyDelta_Check(obj_ptr))
+ return 0;
+ return obj_ptr;
+ }
+
+ static void construct(PyObject* obj_ptr,
+ python::converter::rvalue_from_python_stage1_data * data)
+ {
+ PyDateTime_Delta const* pydelta
+ = reinterpret_cast<PyDateTime_Delta*>(obj_ptr);
+
+ int days = pydelta->days;
+ bool is_negative = (days < 0);
+ if (is_negative)
+ days = -days;
+
+ // Create time duration object
+ posix_time::time_duration
+ duration = (posix_time::hours(24) * days +
+ posix_time::seconds(pydelta->seconds) +
+ posix_time::microseconds(pydelta->microseconds));
+ if (is_negative)
+ duration = duration.invert_sign();
+
+ void * storage =
+ reinterpret_cast<converter::rvalue_from_python_storage
+ <posix_time::time_duration> *>
+ (data)->storage.bytes;
+
+ new (storage) posix_time::time_duration(duration);
+ data->convertible = storage;
+ }
+};
+
+typedef register_python_conversion<time_duration_t,
+ duration_to_python, duration_from_python>
+ duration_python_conversion;
+
+
+datetime_t py_parse_datetime(const string& str) {
+ return parse_datetime(str);
+}
+
+date_t py_parse_date(const string& str) {
+ return parse_date(str);
+}
+
+void export_times()
+{
+ datetime_python_conversion();
+ date_python_conversion();
+ duration_python_conversion();
+
+ register_optional_to_python<datetime_t>();
+ register_optional_to_python<date_t>();
+
+ scope().attr("parse_datetime") = &py_parse_datetime;
+ scope().attr("parse_date") = &py_parse_date;
+ scope().attr("times_initialize") = &times_initialize;
+ scope().attr("times_shutdown") = &times_shutdown;
+
+#if 0
+ class_< interval_t > ("Interval")
+ ;
+#endif
+}
+
+} // namespace ledger
diff --git a/src/py_utils.cc b/src/py_utils.cc
new file mode 100644
index 00000000..5203599f
--- /dev/null
+++ b/src/py_utils.cc
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "pyutils.h"
+#include "pyfstream.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+struct bool_to_python
+{
+ static PyObject * convert(const bool truth)
+ {
+ if (truth)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+ }
+};
+
+struct bool_from_python
+{
+ static void* convertible(PyObject* obj_ptr)
+ {
+ if (!PyBool_Check(obj_ptr)) return 0;
+ return obj_ptr;
+ }
+
+ static void construct(PyObject* obj_ptr,
+ converter::rvalue_from_python_stage1_data* data)
+ {
+ void * storage =
+ ((converter::rvalue_from_python_storage<bool>*) data)->storage.bytes;
+ if (obj_ptr == Py_True)
+ new (storage) bool(true);
+ else
+ new (storage) bool(false);
+ data->convertible = storage;
+ }
+};
+
+typedef register_python_conversion<bool, bool_to_python, bool_from_python>
+ bool_python_conversion;
+
+
+struct string_to_python
+{
+ static PyObject* convert(const string& str)
+ {
+ // Return bytes, not characters; see __unicode__ methods for that
+ return incref(object(static_cast<const std::string&>(str)).ptr());
+ }
+};
+
+struct string_from_python
+{
+ static void* convertible(PyObject* obj_ptr)
+ {
+ if (!PyUnicode_Check(obj_ptr) &&
+ !PyString_Check(obj_ptr)) return 0;
+ return obj_ptr;
+ }
+
+ static void construct(PyObject* obj_ptr,
+ converter::rvalue_from_python_stage1_data* data)
+ {
+ if (PyString_Check(obj_ptr)) {
+ const char* value = PyString_AsString(obj_ptr);
+ if (value == 0) throw_error_already_set();
+ void* storage =
+ reinterpret_cast<converter::rvalue_from_python_storage<string> *>
+ (data)->storage.bytes;
+ new (storage) string(value);
+ data->convertible = storage;
+ } else {
+ VERIFY(PyUnicode_Check(obj_ptr));
+
+ Py_ssize_t size = PyUnicode_GET_SIZE(obj_ptr);
+ const Py_UNICODE* value = PyUnicode_AS_UNICODE(obj_ptr);
+
+ string str;
+ if (sizeof(Py_UNICODE) == 2) // UTF-16
+ utf8::unchecked::utf16to8(value, value + size, std::back_inserter(str));
+ else if (sizeof(Py_UNICODE) == 4) // UTF-32
+ utf8::unchecked::utf32to8(value, value + size, std::back_inserter(str));
+ else
+ assert(! "Py_UNICODE has an unexpected size");
+
+ if (value == 0) throw_error_already_set();
+ void* storage =
+ reinterpret_cast<converter::rvalue_from_python_storage<string> *>
+ (data)->storage.bytes;
+ new (storage) string(str);
+ data->convertible = storage;
+ }
+ }
+};
+
+typedef register_python_conversion<string, string_to_python, string_from_python>
+ string_python_conversion;
+
+
+struct istream_to_python
+{
+ static PyObject* convert(const std::istream&)
+ {
+ return incref(boost::python::detail::none());
+ }
+};
+
+struct istream_from_python
+{
+ static void* convertible(PyObject* obj_ptr)
+ {
+ if (!PyFile_Check(obj_ptr)) return 0;
+ return obj_ptr;
+ }
+
+ static void construct(PyObject* obj_ptr,
+ converter::rvalue_from_python_stage1_data* data)
+ {
+ void* storage =
+ reinterpret_cast<converter::rvalue_from_python_storage<pyifstream> *>
+ (data)->storage.bytes;
+ new (storage) pyifstream(reinterpret_cast<PyFileObject *>(obj_ptr));
+ data->convertible = storage;
+ }
+};
+
+typedef register_python_conversion<std::istream,
+ istream_to_python, istream_from_python>
+ istream_python_conversion;
+
+
+struct ostream_to_python
+{
+ static PyObject* convert(const std::ostream&)
+ {
+ return incref(boost::python::detail::none());
+ }
+};
+
+struct ostream_from_python
+{
+ static void* convertible(PyObject* obj_ptr)
+ {
+ if (!PyFile_Check(obj_ptr)) return 0;
+ return obj_ptr;
+ }
+
+ static void construct(PyObject* obj_ptr,
+ converter::rvalue_from_python_stage1_data* data)
+ {
+ void* storage =
+ reinterpret_cast<converter::rvalue_from_python_storage<pyofstream> *>
+ (data)->storage.bytes;
+ new (storage) pyofstream(reinterpret_cast<PyFileObject *>(obj_ptr));
+ data->convertible = storage;
+ }
+};
+
+typedef register_python_conversion<std::ostream,
+ ostream_to_python, ostream_from_python>
+ ostream_python_conversion;
+
+
+void export_utils()
+{
+ class_< supports_flags<uint_least8_t> > ("SupportFlags8")
+ .def(init<supports_flags<uint_least8_t> >())
+ .def(init<uint_least8_t>())
+
+ .add_property("flags",
+ &supports_flags<uint_least8_t>::flags,
+ &supports_flags<uint_least8_t>::set_flags)
+ .def("has_flags", &supports_flags<uint_least8_t>::has_flags)
+ .def("clear_flags", &supports_flags<uint_least8_t>::clear_flags)
+ .def("add_flags", &supports_flags<uint_least8_t>::add_flags)
+ .def("drop_flags", &supports_flags<uint_least8_t>::drop_flags)
+ ;
+
+ class_< supports_flags<uint_least16_t> > ("SupportFlags16")
+ .def(init<supports_flags<uint_least16_t> >())
+ .def(init<uint_least16_t>())
+
+ .add_property("flags",
+ &supports_flags<uint_least16_t>::flags,
+ &supports_flags<uint_least16_t>::set_flags)
+ .def("has_flags", &supports_flags<uint_least16_t>::has_flags)
+ .def("clear_flags", &supports_flags<uint_least16_t>::clear_flags)
+ .def("add_flags", &supports_flags<uint_least16_t>::add_flags)
+ .def("drop_flags", &supports_flags<uint_least16_t>::drop_flags)
+ ;
+
+#if 0
+ class_< basic_flags_t<uint_least8_t>,
+ bases<supports_flags<uint_least8_t> > > ("BasicFlags8")
+ .def(init<uint_least8_t>())
+
+ .def("plus_flags", &basic_flags_t<uint_least8_t>::plus_flags)
+ .def("minus_flags", &basic_flags_t<uint_least8_t>::minus_flags)
+ ;
+#endif
+
+ class_< delegates_flags<uint_least16_t>,
+ boost::noncopyable > ("DelegatesFlags16", no_init)
+ .add_property("flags",
+ &delegates_flags<uint_least16_t>::flags,
+ &delegates_flags<uint_least16_t>::set_flags)
+ .def("has_flags", &delegates_flags<uint_least16_t>::has_flags)
+ .def("clear_flags", &delegates_flags<uint_least16_t>::clear_flags)
+ .def("add_flags", &delegates_flags<uint_least16_t>::add_flags)
+ .def("drop_flags", &delegates_flags<uint_least16_t>::drop_flags)
+ ;
+
+ bool_python_conversion();
+ string_python_conversion();
+ istream_python_conversion();
+ ostream_python_conversion();
+}
+
+} // namespace ledger
diff --git a/src/py_value.cc b/src/py_value.cc
new file mode 100644
index 00000000..713dc3d4
--- /dev/null
+++ b/src/py_value.cc
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "pyutils.h"
+#include "commodity.h"
+#include "annotate.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(value_overloads, value, 0, 2)
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(exchange_commodities_overloads,
+ exchange_commodities, 1, 2)
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(set_string_overloads, set_string, 0, 2)
+
+namespace {
+
+ boost::optional<value_t> py_value_0(const value_t& value) {
+ return value.value(false, CURRENT_TIME());
+ }
+ boost::optional<value_t> py_value_1(const value_t& value,
+ commodity_t& in_terms_of) {
+ return value.value(false, CURRENT_TIME(), in_terms_of);
+ }
+ boost::optional<value_t> py_value_2(const value_t& value,
+ commodity_t& in_terms_of,
+ datetime_t& moment) {
+ return value.value(false, moment, in_terms_of);
+ }
+
+ PyObject * py_base_type(value_t& value)
+ {
+ if (value.is_boolean()) {
+ return (PyObject *)&PyBool_Type;
+ }
+ else if (value.is_long()) {
+ return (PyObject *)&PyInt_Type;
+ }
+ else if (value.is_string()) {
+ return (PyObject *)&PyUnicode_Type;
+ }
+ else {
+ object typeobj(object(value).attr("__class__"));
+ return typeobj.ptr();
+ }
+ }
+
+ string py_dump(const value_t& value) {
+ std::ostringstream buf;
+ value.dump(buf);
+ return buf.str();
+ }
+
+ string py_dump_relaxed(const value_t& value) {
+ std::ostringstream buf;
+ value.dump(buf, true);
+ return buf.str();
+ }
+
+ void py_set_string(value_t& value, const string& str) {
+ return value.set_string(str);
+ }
+
+ annotation_t& py_value_annotation(value_t& value) {
+ return value.annotation();
+ }
+
+ value_t py_strip_annotations_0(value_t& value) {
+ return value.strip_annotations(keep_details_t());
+ }
+ value_t py_strip_annotations_1(value_t& value, const keep_details_t& keep) {
+ return value.strip_annotations(keep);
+ }
+
+ PyObject * py_value_unicode(value_t& value) {
+ return str_to_py_unicode(value.to_string());
+ }
+
+} // unnamed namespace
+
+#define EXC_TRANSLATOR(type) \
+ void exc_translate_ ## type(const type& err) { \
+ PyErr_SetString(PyExc_ArithmeticError, err.what()); \
+ }
+
+EXC_TRANSLATOR(value_error)
+
+void export_value()
+{
+ enum_< value_t::type_t >("ValueType")
+ .value("Void", value_t::VOID)
+ .value("Boolean", value_t::BOOLEAN)
+ .value("DateTime", value_t::DATETIME)
+ .value("Date", value_t::DATE)
+ .value("Integer", value_t::INTEGER)
+ .value("Amount", value_t::AMOUNT)
+ .value("Balance", value_t::BALANCE)
+ .value("String", value_t::STRING)
+ .value("Sequence", value_t::SEQUENCE)
+ .value("Scope", value_t::SCOPE)
+ ;
+
+ class_< value_t > ("Value")
+ .def("initialize", &value_t::initialize)
+ .staticmethod("initialize")
+ .def("shutdown", &value_t::shutdown)
+ .staticmethod("shutdown")
+
+ .def(init<bool>())
+ .def(init<datetime_t>())
+ .def(init<date_t>())
+ .def(init<long>())
+ .def(init<double>())
+ .def(init<amount_t>())
+ .def(init<balance_t>())
+ .def(init<mask_t>())
+ .def(init<std::string>())
+ // jww (2009-11-02): Need to support conversion eof value_t::sequence_t
+ //.def(init<value_t::sequence_t>())
+ .def(init<value_t>())
+
+ .def("is_equal_to", &value_t::is_equal_to)
+ .def("is_less_than", &value_t::is_less_than)
+ .def("is_greater_than", &value_t::is_greater_than)
+
+ .def(self == self)
+ .def(self == long())
+ .def(long() == self)
+ .def(self == other<amount_t>())
+ .def(other<amount_t>() == self)
+ .def(self == other<balance_t>())
+ .def(other<balance_t>() == self)
+
+ .def(self != self)
+ .def(self != long())
+ .def(long() != self)
+ .def(self != other<amount_t>())
+ .def(other<amount_t>() != self)
+ .def(self != other<balance_t>())
+ .def(other<balance_t>() != self)
+
+ .def(! self)
+
+ .def(self < self)
+ .def(self < long())
+ .def(long() < self)
+ .def(self < other<amount_t>())
+ .def(other<amount_t>() < self)
+
+ .def(self <= self)
+ .def(self <= long())
+ .def(long() <= self)
+ .def(self <= other<amount_t>())
+ .def(other<amount_t>() <= self)
+
+ .def(self > self)
+ .def(self > long())
+ .def(long() > self)
+ .def(self > other<amount_t>())
+ .def(other<amount_t>() > self)
+
+ .def(self >= self)
+ .def(self >= long())
+ .def(long() >= self)
+ .def(self >= other<amount_t>())
+ .def(other<amount_t>() >= self)
+
+ .def(self += self)
+ .def(self += long())
+ .def(self += other<amount_t>())
+ .def(self += other<balance_t>())
+
+ .def(self + self)
+ .def(self + long())
+ .def(long() + self)
+ .def(self + other<amount_t>())
+ .def(other<amount_t>() + self)
+ .def(self + other<balance_t>())
+
+ .def(self -= self)
+ .def(self -= long())
+ .def(self -= other<amount_t>())
+ .def(self -= other<balance_t>())
+
+ .def(self - self)
+ .def(self - long())
+ .def(long() - self)
+ .def(self - other<amount_t>())
+ .def(other<amount_t>() - self)
+ .def(self - other<balance_t>())
+
+ .def(self *= self)
+ .def(self *= long())
+ .def(self *= other<amount_t>())
+
+ .def(self * self)
+ .def(self * long())
+ .def(long() * self)
+ .def(self * other<amount_t>())
+ .def(other<amount_t>() * self)
+
+ .def(self /= self)
+ .def(self /= long())
+ .def(self /= other<amount_t>())
+
+ .def(self / self)
+ .def(self / long())
+ .def(long() / self)
+ .def(self / other<amount_t>())
+ .def(other<amount_t>() / self)
+
+ .def("negated", &value_t::negated)
+ .def("in_place_negate", &value_t::in_place_negate)
+ .def("in_place_not", &value_t::in_place_not)
+ .def(- self)
+
+ .def("abs", &value_t::abs)
+ .def("__abs__", &value_t::abs)
+
+ .def("rounded", &value_t::rounded)
+ .def("in_place_round", &value_t::in_place_round)
+ .def("truncated", &value_t::truncated)
+ .def("in_place_truncate", &value_t::in_place_truncate)
+ .def("floored", &value_t::floored)
+ .def("in_place_floor", &value_t::in_place_floor)
+ .def("unrounded", &value_t::unrounded)
+ .def("in_place_unround", &value_t::in_place_unround)
+ .def("reduced", &value_t::reduced)
+ .def("in_place_reduce", &value_t::in_place_reduce)
+ .def("unreduced", &value_t::unreduced)
+ .def("in_place_unreduce", &value_t::in_place_unreduce)
+
+ .def("value", py_value_0)
+ .def("value", py_value_1, args("in_terms_of"))
+ .def("value", py_value_2, args("in_terms_of", "moment"))
+
+ .def("value", &value_t::value, value_overloads())
+ .def("price", &value_t::price)
+ .def("exchange_commodities", &value_t::exchange_commodities,
+ exchange_commodities_overloads())
+
+ .def("__nonzero__", &value_t::is_nonzero)
+ .def("is_nonzero", &value_t::is_nonzero)
+ .def("is_realzero", &value_t::is_realzero)
+ .def("is_zero", &value_t::is_zero)
+ .def("is_null", &value_t::is_null)
+
+ .def("type", &value_t::type)
+ .def("is_type", &value_t::is_type)
+
+ .def("is_boolean", &value_t::is_boolean)
+ .def("set_boolean", &value_t::set_boolean)
+
+ .def("is_datetime", &value_t::is_datetime)
+ .def("set_datetime", &value_t::set_datetime)
+
+ .def("is_date", &value_t::is_date)
+ .def("set_date", &value_t::set_date)
+
+ .def("is_long", &value_t::is_long)
+ .def("set_long", &value_t::set_long)
+
+ .def("is_amount", &value_t::is_amount)
+ .def("is_amount", &value_t::is_amount)
+
+ .def("is_balance", &value_t::is_balance)
+ .def("is_balance", &value_t::is_balance)
+
+ .def("is_string", &value_t::is_string)
+ .def("set_string", py_set_string)
+
+ .def("is_mask", &value_t::is_mask)
+ .def("is_mask", &value_t::is_mask)
+
+ .def("is_sequence", &value_t::is_sequence)
+ .def("set_sequence", &value_t::set_sequence)
+
+ .def("to_boolean", &value_t::to_boolean)
+ .def("to_long", &value_t::to_long)
+ .def("__int__", &value_t::to_long)
+ .def("to_datetime", &value_t::to_datetime)
+ .def("to_date", &value_t::to_date)
+ .def("to_amount", &value_t::to_amount)
+ .def("to_balance", &value_t::to_balance)
+ .def("__str__", &value_t::to_string)
+ .def("__unicode__", py_value_unicode)
+ .def("to_string", &value_t::to_string)
+ .def("to_mask", &value_t::to_mask)
+ .def("to_sequence", &value_t::to_sequence)
+
+ .def("__unicode__", py_dump_relaxed)
+ .def("__repr__", py_dump)
+
+ .def("casted", &value_t::casted)
+ .def("in_place_cast", &value_t::in_place_cast)
+ .def("simplified", &value_t::simplified)
+ .def("in_place_simplify", &value_t::in_place_simplify)
+
+ .def("number", &value_t::number)
+
+ .def("annotate", &value_t::annotate)
+ .def("has_annotation", &value_t::has_annotation)
+ .add_property("annotation",
+ make_function(py_value_annotation,
+ return_internal_reference<>()))
+ .def("strip_annotations", py_strip_annotations_0)
+ .def("strip_annotations", py_strip_annotations_1)
+
+#if 0
+ .def("__getitem__", &value_t::operator[])
+#endif
+ .def("push_back", &value_t::push_back)
+ .def("pop_back", &value_t::pop_back)
+ .def("size", &value_t::size)
+
+ .def("label", &value_t::label)
+
+ .def("valid", &value_t::valid)
+
+ .def("basetype", py_base_type)
+ ;
+
+ class_< value_t::sequence_t > ("ValueSequence")
+ .def(vector_indexing_suite< value_t::sequence_t >());
+ ;
+
+ scope().attr("NULL_VALUE") = NULL_VALUE;
+ scope().attr("string_value") = &string_value;
+ scope().attr("mask_value") = &mask_value;
+ scope().attr("value_context") = &value_context;
+
+ register_optional_to_python<value_t>();
+
+ implicitly_convertible<long, value_t>();
+ implicitly_convertible<string, value_t>();
+ implicitly_convertible<amount_t, value_t>();
+ implicitly_convertible<balance_t, value_t>();
+ implicitly_convertible<mask_t, value_t>();
+ implicitly_convertible<date_t, value_t>();
+ implicitly_convertible<datetime_t, value_t>();
+
+#define EXC_TRANSLATE(type) \
+ register_exception_translator<type>(&exc_translate_ ## type);
+
+ EXC_TRANSLATE(value_error);
+}
+
+} // namespace ledger
diff --git a/src/py_xact.cc b/src/py_xact.cc
new file mode 100644
index 00000000..59c599d9
--- /dev/null
+++ b/src/py_xact.cc
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "pyutils.h"
+#include "xact.h"
+#include "post.h"
+
+namespace ledger {
+
+using namespace boost::python;
+
+namespace {
+
+ long posts_len(xact_base_t& xact)
+ {
+ return xact.posts.size();
+ }
+
+ post_t& posts_getitem(xact_base_t& xact, long i)
+ {
+ static long last_index = 0;
+ static xact_base_t * last_xact = NULL;
+ static posts_list::iterator elem;
+
+ long len = xact.posts.size();
+
+ if (labs(i) >= len) {
+ PyErr_SetString(PyExc_IndexError, _("Index out of range"));
+ throw_error_already_set();
+ }
+
+ if (&xact == last_xact && i == last_index + 1) {
+ last_index = i;
+ return **++elem;
+ }
+
+ long x = i < 0 ? len + i : i;
+ elem = xact.posts.begin();
+ while (--x >= 0)
+ elem++;
+
+ last_xact = &xact;
+ last_index = i;
+
+ return **elem;
+ }
+
+} // unnamed namespace
+
+using namespace boost::python;
+
+void export_xact()
+{
+ class_< xact_base_t, bases<item_t> > ("TransactionBase")
+ .add_property("journal",
+ make_getter(&xact_base_t::journal,
+ return_internal_reference<>()),
+ make_setter(&xact_base_t::journal,
+ with_custodian_and_ward<1, 2>()))
+
+ .def("__len__", posts_len)
+ .def("__getitem__", posts_getitem,
+ return_internal_reference<>())
+
+ .def("add_post", &xact_base_t::add_post, with_custodian_and_ward<1, 2>())
+ .def("remove_post", &xact_base_t::add_post)
+
+ .def("finalize", &xact_base_t::finalize)
+
+ .def("__iter__", range<return_internal_reference<> >
+ (&xact_t::posts_begin, &xact_t::posts_end))
+ .def("posts", range<return_internal_reference<> >
+ (&xact_t::posts_begin, &xact_t::posts_end))
+
+ .def("valid", &xact_base_t::valid)
+ ;
+
+ class_< xact_t, bases<xact_base_t> > ("Transaction")
+ .add_property("code",
+ make_getter(&xact_t::code),
+ make_setter(&xact_t::code))
+ .add_property("payee",
+ make_getter(&xact_t::payee),
+ make_setter(&xact_t::payee))
+
+ .def("add_post", &xact_t::add_post, with_custodian_and_ward<1, 2>())
+
+ .def("magnitude", &xact_t::magnitude)
+ .def("idstring", &xact_t::idstring)
+ .def("id", &xact_t::id)
+
+ .def("lookup", &xact_t::lookup)
+
+ .def("has_xdata", &xact_t::has_xdata)
+ .def("clear_xdata", &xact_t::clear_xdata)
+
+ .def("valid", &xact_t::valid)
+ ;
+
+ class_< auto_xact_t, bases<xact_base_t> > ("AutomatedTransaction")
+ .def(init<predicate_t>())
+
+ .add_property("predicate",
+ make_getter(&auto_xact_t::predicate),
+ make_setter(&auto_xact_t::predicate))
+
+ .def("extend_xact", &auto_xact_t::extend_xact)
+ ;
+
+ class_< period_xact_t, bases<xact_base_t> > ("PeriodicTransaction")
+ .def(init<string>())
+
+ .add_property("period",
+ make_getter(&period_xact_t::period),
+ make_setter(&period_xact_t::period))
+ .add_property("period_string",
+ make_getter(&period_xact_t::period_string),
+ make_setter(&period_xact_t::period_string))
+ ;
+}
+
+} // namespace ledger
diff --git a/src/pyfstream.h b/src/pyfstream.h
new file mode 100644
index 00000000..3da37523
--- /dev/null
+++ b/src/pyfstream.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#ifndef _PYFSTREAM_H
+#define _PYFSTREAM_H
+
+// pyofstream
+// - a stream that writes on a Python file object
+
+class pyoutbuf : public boost::noncopyable, public std::streambuf
+{
+ pyoutbuf();
+
+protected:
+ PyFileObject * fo; // Python file object
+
+public:
+ // constructor
+ pyoutbuf(PyFileObject * _fo) : fo(_fo) {
+ TRACE_CTOR(pyoutbuf, "PyFileObject *");
+ }
+ ~pyoutbuf() throw() {
+ TRACE_DTOR(pyoutbuf);
+ }
+
+protected:
+ // write one character
+ virtual int_type overflow (int_type c) {
+ if (c != EOF) {
+ char z[2];
+ z[0] = static_cast<char>(c);
+ z[1] = '\0';
+ if (PyFile_WriteString(z, reinterpret_cast<PyObject *>(fo)) < 0) {
+ return EOF;
+ }
+ }
+ return c;
+ }
+
+ // write multiple characters
+ virtual std::streamsize xsputn (const char* s, std::streamsize num) {
+ char * buf = new char[num + 1];
+ std::strncpy(buf, s, num);
+ buf[num] = '\0';
+ if (PyFile_WriteString(buf, reinterpret_cast<PyObject *>(fo)) < 0)
+ num = 0;
+ boost::checked_array_delete(buf);
+ return num;
+ }
+};
+
+class pyofstream : public boost::noncopyable, public std::ostream
+{
+ pyofstream();
+
+protected:
+ pyoutbuf buf;
+
+public:
+ pyofstream (PyFileObject * fo) : std::ostream(0), buf(fo) {
+ TRACE_CTOR(pyofstream, "PyFileObject *");
+ rdbuf(&buf);
+ }
+ ~pyofstream() throw() {
+ TRACE_DTOR(pyofstream);
+ }
+};
+
+// pyifstream
+// - a stream that reads on a file descriptor
+
+class pyinbuf : public boost::noncopyable, public std::streambuf
+{
+ pyinbuf();
+
+protected:
+ PyFileObject * fo; // Python file object
+
+protected:
+ /* data buffer:
+ * - at most, pbSize characters in putback area plus
+ * - at most, bufSize characters in ordinary read buffer
+ */
+ static const size_t pbSize = 4; // size of putback area
+ static const size_t bufSize = 1024; // size of the data buffer
+ char buffer[bufSize + pbSize]; // data buffer
+
+public:
+ /* constructor
+ * - initialize file descriptor
+ * - initialize empty data buffer
+ * - no putback area
+ * => force underflow()
+ */
+ pyinbuf (PyFileObject * _fo) : fo(_fo) {
+ TRACE_CTOR(pyinbuf, "PyFileObject *");
+
+ setg (buffer+pbSize, // beginning of putback area
+ buffer+pbSize, // read position
+ buffer+pbSize); // end position
+ }
+ ~pyinbuf() throw() {
+ TRACE_DTOR(pyinbuf);
+ }
+
+protected:
+ // insert new characters into the buffer
+ virtual int_type underflow () {
+#ifndef _MSC_VER
+ using std::memmove;
+#endif
+
+ // is read position before end of buffer?
+ if (gptr() < egptr()) {
+ return traits_type::to_int_type(*gptr());
+ }
+
+ /* process size of putback area
+ * - use number of characters read
+ * - but at most size of putback area
+ */
+ size_t numPutback;
+ numPutback = gptr() - eback();
+ if (numPutback > pbSize) {
+ numPutback = pbSize;
+ }
+
+ /* copy up to pbSize characters previously read into
+ * the putback area
+ */
+ memmove (buffer+(pbSize-numPutback), gptr()-numPutback,
+ numPutback);
+
+ // read at most bufSize new characters
+ PyObject *line = PyFile_GetLine(reinterpret_cast<PyObject *>(fo), bufSize);
+ if (! line || ! PyString_Check(line)) {
+ // ERROR or EOF
+ return EOF;
+ }
+
+ Py_ssize_t num = PyString_Size(line);
+ if (num == 0)
+ return EOF;
+
+ memmove (buffer+pbSize, PyString_AsString(line), num);
+
+ // reset buffer pointers
+ setg (buffer+(pbSize-numPutback), // beginning of putback area
+ buffer+pbSize, // read position
+ buffer+pbSize+num); // end of buffer
+
+ // return next character
+ return traits_type::to_int_type(*gptr());
+ }
+};
+
+class pyifstream : public boost::noncopyable, public std::istream
+{
+ pyifstream();
+
+protected:
+ pyinbuf buf;
+
+public:
+ pyifstream (PyFileObject * fo) : std::istream(0), buf(fo) {
+ TRACE_CTOR(pyifstream, "PyFileObject *");
+ rdbuf(&buf);
+ }
+ ~pyifstream() throw() {
+ TRACE_DTOR(pyifstream);
+ }
+};
+
+#endif // _PYFSTREAM_H
diff --git a/src/pyinterp.cc b/src/pyinterp.cc
new file mode 100644
index 00000000..0701176f
--- /dev/null
+++ b/src/pyinterp.cc
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+#include "account.h"
+#include "xact.h"
+#include "post.h"
+
+namespace ledger {
+
+using namespace python;
+
+shared_ptr<python_interpreter_t> python_session;
+
+char * argv0;
+
+void export_account();
+void export_amount();
+void export_balance();
+void export_commodity();
+void export_expr();
+void export_format();
+void export_item();
+void export_journal();
+void export_post();
+void export_times();
+void export_utils();
+void export_value();
+void export_xact();
+
+void initialize_for_python()
+{
+ export_times();
+ export_utils();
+ export_commodity();
+ export_amount();
+ export_value();
+ export_account();
+ export_balance();
+ export_expr();
+ export_format();
+ export_item();
+ export_post();
+ export_xact();
+ export_journal();
+}
+
+struct python_run
+{
+ object result;
+
+ python_run(python_interpreter_t * intepreter,
+ const string& str, int input_mode)
+ : result(handle<>(borrowed(PyRun_String(str.c_str(), input_mode,
+ intepreter->main_nspace.ptr(),
+ intepreter->main_nspace.ptr())))) {}
+ operator object() {
+ return result;
+ }
+};
+
+void python_interpreter_t::initialize()
+{
+ TRACE_START(python_init, 1, "Initialized Python");
+
+ try {
+ DEBUG("python.interp", "Initializing Python");
+
+ Py_Initialize();
+ assert(Py_IsInitialized());
+
+ hack_system_paths();
+
+ object main_module = python::import("__main__");
+ if (! main_module)
+ throw_(std::runtime_error,
+ _("Python failed to initialize (couldn't find __main__)"));
+
+ main_nspace = extract<dict>(main_module.attr("__dict__"));
+ if (! main_nspace)
+ throw_(std::runtime_error,
+ _("Python failed to initialize (couldn't find __dict__)"));
+
+ python::detail::init_module("ledger", &initialize_for_python);
+
+ is_initialized = true;
+ }
+ catch (const error_already_set&) {
+ PyErr_Print();
+ throw_(std::runtime_error, _("Python failed to initialize"));
+ }
+
+ TRACE_FINISH(python_init, 1);
+}
+
+void python_interpreter_t::hack_system_paths()
+{
+ // Hack ledger.__path__ so it points to a real location
+ python::object sys_module = python::import("sys");
+ python::object sys_dict = sys_module.attr("__dict__");
+
+ python::list paths(sys_dict["path"]);
+
+#if defined(DEBUG_ON)
+ bool path_initialized = false;
+#endif
+ int n = python::extract<int>(paths.attr("__len__")());
+ for (int i = 0; i < n; i++) {
+ python::extract<std::string> str(paths[i]);
+ path pathname(str);
+ DEBUG("python.interp", "sys.path = " << pathname);
+
+ if (exists(pathname / "ledger" / "__init__.py")) {
+ if (python::object module_ledger = python::import("ledger")) {
+ DEBUG("python.interp",
+ "Setting ledger.__path__ = " << (pathname / "ledger"));
+
+ python::object ledger_dict = module_ledger.attr("__dict__");
+ python::list temp_list;
+ temp_list.append((pathname / "ledger").string());
+
+ ledger_dict["__path__"] = temp_list;
+ } else {
+ throw_(std::runtime_error,
+ _("Python failed to initialize (couldn't find ledger)"));
+ }
+#if defined(DEBUG_ON)
+ path_initialized = true;
+#endif
+ break;
+ }
+ }
+#if defined(DEBUG_ON)
+ if (! path_initialized)
+ DEBUG("python.init",
+ "Ledger failed to find 'ledger/__init__.py' on the PYTHONPATH");
+#endif
+}
+
+object python_interpreter_t::import_into_main(const string& str)
+{
+ if (! is_initialized)
+ initialize();
+
+ try {
+ object mod = python::import(str.c_str());
+ if (! mod)
+ throw_(std::runtime_error,
+ _("Failed to import Python module %1") << str);
+
+ // Import all top-level entries directly into the main namespace
+ main_nspace.update(mod.attr("__dict__"));
+
+ return mod;
+ }
+ catch (const error_already_set&) {
+ PyErr_Print();
+ }
+ return object();
+}
+
+object python_interpreter_t::import_option(const string& str)
+{
+ path file(str);
+
+ python::object sys_module = python::import("sys");
+ python::object sys_dict = sys_module.attr("__dict__");
+
+ python::list paths(sys_dict["path"]);
+
+#if BOOST_VERSION >= 103700
+ paths.insert(0, file.parent_path().string());
+ sys_dict["path"] = paths;
+
+ string name = file.filename();
+ if (contains(name, ".py"))
+ name = file.stem();
+#else // BOOST_VERSION >= 103700
+ paths.insert(0, file.branch_path().string());
+ sys_dict["path"] = paths;
+
+ string name = file.leaf();
+#endif // BOOST_VERSION >= 103700
+
+ return python::import(python::str(name.c_str()));
+}
+
+object python_interpreter_t::eval(std::istream& in, py_eval_mode_t mode)
+{
+ bool first = true;
+ string buffer;
+ buffer.reserve(4096);
+
+ while (! in.eof()) {
+ char buf[256];
+ in.getline(buf, 255);
+ if (buf[0] == '!')
+ break;
+ if (first)
+ first = false;
+ else
+ buffer += "\n";
+ buffer += buf;
+ }
+
+ if (! is_initialized)
+ initialize();
+
+ try {
+ int input_mode = -1;
+ switch (mode) {
+ case PY_EVAL_EXPR: input_mode = Py_eval_input; break;
+ case PY_EVAL_STMT: input_mode = Py_single_input; break;
+ case PY_EVAL_MULTI: input_mode = Py_file_input; break;
+ }
+
+ return python_run(this, buffer, input_mode);
+ }
+ catch (const error_already_set&) {
+ PyErr_Print();
+ throw_(std::runtime_error, _("Failed to evaluate Python code"));
+ }
+ return object();
+}
+
+object python_interpreter_t::eval(const string& str, py_eval_mode_t mode)
+{
+ if (! is_initialized)
+ initialize();
+
+ try {
+ int input_mode = -1;
+ switch (mode) {
+ case PY_EVAL_EXPR: input_mode = Py_eval_input; break;
+ case PY_EVAL_STMT: input_mode = Py_single_input; break;
+ case PY_EVAL_MULTI: input_mode = Py_file_input; break;
+ }
+
+ return python_run(this, str, input_mode);
+ }
+ catch (const error_already_set&) {
+ PyErr_Print();
+ throw_(std::runtime_error, _("Failed to evaluate Python code"));
+ }
+ return object();
+}
+
+value_t python_interpreter_t::python_command(call_scope_t& args)
+{
+ if (! is_initialized)
+ initialize();
+
+ char ** argv(new char *[args.size() + 1]);
+
+ argv[0] = new char[std::strlen(argv0) + 1];
+ std::strcpy(argv[0], argv0);
+
+ for (std::size_t i = 0; i < args.size(); i++) {
+ string arg = args[i].as_string();
+ argv[i + 1] = new char[arg.length() + 1];
+ std::strcpy(argv[i + 1], arg.c_str());
+ }
+
+ int status = 1;
+
+ try {
+ status = Py_Main(static_cast<int>(args.size()) + 1, argv);
+ }
+ catch (const error_already_set&) {
+ PyErr_Print();
+ throw_(std::runtime_error, _("Failed to execute Python module"));
+ }
+ catch (...) {
+ for (std::size_t i = 0; i < args.size() + 1; i++)
+ delete[] argv[i];
+ delete[] argv;
+ throw;
+ }
+
+ for (std::size_t i = 0; i < args.size() + 1; i++)
+ delete[] argv[i];
+ delete[] argv;
+
+ if (status != 0)
+ throw status;
+
+ return NULL_VALUE;
+}
+
+value_t python_interpreter_t::server_command(call_scope_t& args)
+{
+ if (! is_initialized)
+ initialize();
+
+ python::object server_module;
+
+ try {
+ server_module = python::import("ledger.server");
+ if (! server_module)
+ throw_(std::runtime_error,
+ _("Could not import ledger.server; please check your PYTHONPATH"));
+ }
+ catch (const error_already_set&) {
+ PyErr_Print();
+ throw_(std::runtime_error,
+ _("Could not import ledger.server; please check your PYTHONPATH"));
+ }
+
+ if (python::object main_function = server_module.attr("main")) {
+ functor_t func(main_function, "main");
+ try {
+ func(args);
+ }
+ catch (const error_already_set&) {
+ PyErr_Print();
+ throw_(std::runtime_error,
+ _("Error while invoking ledger.server's main() function"));
+ }
+ return true;
+ } else {
+ throw_(std::runtime_error,
+ _("The ledger.server module is missing its main() function!"));
+ }
+
+ return false;
+}
+
+option_t<python_interpreter_t> *
+python_interpreter_t::lookup_option(const char * p)
+{
+ switch (*p) {
+ case 'i':
+ OPT(import_);
+ break;
+ }
+ return NULL;
+}
+
+expr_t::ptr_op_t python_interpreter_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
+{
+ // Give our superclass first dibs on symbol definitions
+ if (expr_t::ptr_op_t op = session_t::lookup(kind, name))
+ return op;
+
+ switch (kind) {
+ case symbol_t::FUNCTION:
+ if (option_t<python_interpreter_t> * handler = lookup_option(name.c_str()))
+ return MAKE_OPT_FUNCTOR(python_interpreter_t, handler);
+
+ if (is_initialized && main_nspace.has_key(name.c_str())) {
+ DEBUG("python.interp", "Python lookup: " << name);
+
+ if (python::object obj = main_nspace.get(name.c_str()))
+ return WRAP_FUNCTOR(functor_t(obj, name));
+ }
+ break;
+
+ case symbol_t::OPTION:
+ if (option_t<python_interpreter_t> * handler = lookup_option(name.c_str()))
+ return MAKE_OPT_HANDLER(python_interpreter_t, handler);
+ break;
+
+ case symbol_t::PRECOMMAND: {
+ const char * p = name.c_str();
+ switch (*p) {
+ case 'p':
+ if (is_eq(p, "python"))
+ return MAKE_FUNCTOR(python_interpreter_t::python_command);
+ break;
+
+ case 's':
+ if (is_eq(p, "server"))
+ return MAKE_FUNCTOR(python_interpreter_t::server_command);
+ break;
+ }
+ }
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+namespace {
+ void append_value(list& lst, const value_t& value)
+ {
+ if (value.is_scope()) {
+ const scope_t * scope = value.as_scope();
+ if (const post_t * post = dynamic_cast<const post_t *>(scope))
+ lst.append(ptr(post));
+ else if (const xact_t * xact = dynamic_cast<const xact_t *>(scope))
+ lst.append(ptr(xact));
+ else if (const account_t * account =
+ dynamic_cast<const account_t *>(scope))
+ lst.append(ptr(account));
+ else if (const period_xact_t * period_xact =
+ dynamic_cast<const period_xact_t *>(scope))
+ lst.append(ptr(period_xact));
+ else if (const auto_xact_t * auto_xact =
+ dynamic_cast<const auto_xact_t *>(scope))
+ lst.append(ptr(auto_xact));
+ else
+ throw_(std::logic_error,
+ _("Cannot downcast scoped object to specific type"));
+ } else {
+ lst.append(value);
+ }
+ }
+}
+
+value_t python_interpreter_t::functor_t::operator()(call_scope_t& args)
+{
+ try {
+ std::signal(SIGINT, SIG_DFL);
+
+ if (! PyCallable_Check(func.ptr())) {
+ extract<value_t> val(func);
+ std::signal(SIGINT, sigint_handler);
+ if (val.check())
+ return val();
+ return NULL_VALUE;
+ }
+ else if (args.size() > 0) {
+ list arglist;
+ // jww (2009-11-05): What about a single argument which is a sequence,
+ // rather than a sequence of arguments?
+ if (args.value().is_sequence())
+ foreach (const value_t& value, args.value().as_sequence())
+ append_value(arglist, value);
+ else
+ append_value(arglist, args.value());
+
+ if (PyObject * val =
+ PyObject_CallObject(func.ptr(), python::tuple(arglist).ptr())) {
+ extract<value_t> xval(val);
+ value_t result;
+ if (xval.check()) {
+ result = xval();
+ Py_DECREF(val);
+ } else {
+ Py_DECREF(val);
+ throw_(calc_error,
+ _("Could not evaluate Python variable '%1'") << name);
+ }
+ std::signal(SIGINT, sigint_handler);
+ return result;
+ }
+ else if (PyErr_Occurred()) {
+ PyErr_Print();
+ throw_(calc_error, _("Failed call to Python function '%1'") << name);
+ } else {
+ assert(false);
+ }
+ }
+ else {
+ std::signal(SIGINT, sigint_handler);
+ return call<value_t>(func.ptr());
+ }
+ }
+ catch (const error_already_set&) {
+ std::signal(SIGINT, sigint_handler);
+ PyErr_Print();
+ throw_(calc_error, _("Failed call to Python function '%1'") << name);
+ }
+ catch (...) {
+ std::signal(SIGINT, sigint_handler);
+ }
+ std::signal(SIGINT, sigint_handler);
+
+ return NULL_VALUE;
+}
+
+} // namespace ledger
diff --git a/src/pyinterp.h b/src/pyinterp.h
new file mode 100644
index 00000000..f2d7b760
--- /dev/null
+++ b/src/pyinterp.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#ifndef _PYINTERP_H
+#define _PYINTERP_H
+
+#include "session.h"
+
+#if defined(HAVE_BOOST_PYTHON)
+
+namespace ledger {
+
+class python_interpreter_t : public session_t
+{
+public:
+ python::dict main_nspace;
+ bool is_initialized;
+
+ python_interpreter_t()
+ : session_t(), main_nspace(), is_initialized(false) {
+ TRACE_CTOR(python_interpreter_t, "");
+ }
+
+ virtual ~python_interpreter_t() {
+ TRACE_DTOR(python_interpreter_t);
+
+ if (is_initialized)
+ Py_Finalize();
+ }
+
+ void initialize();
+ void hack_system_paths();
+
+ python::object import_into_main(const string& name);
+ python::object import_option(const string& name);
+
+ enum py_eval_mode_t {
+ PY_EVAL_EXPR,
+ PY_EVAL_STMT,
+ PY_EVAL_MULTI
+ };
+
+ python::object eval(std::istream& in,
+ py_eval_mode_t mode = PY_EVAL_EXPR);
+ python::object eval(const string& str,
+ py_eval_mode_t mode = PY_EVAL_EXPR);
+ python::object eval(const char * c_str,
+ py_eval_mode_t mode = PY_EVAL_EXPR) {
+ string str(c_str);
+ return eval(str, mode);
+ }
+
+ value_t python_command(call_scope_t& scope);
+ value_t server_command(call_scope_t& args);
+
+ class functor_t {
+ functor_t();
+
+ protected:
+ python::object func;
+
+ public:
+ string name;
+
+ functor_t(python::object _func, const string& _name)
+ : func(_func), name(_name) {
+ TRACE_CTOR(functor_t, "python::object, const string&");
+ }
+ functor_t(const functor_t& other)
+ : func(other.func), name(other.name) {
+ TRACE_CTOR(functor_t, "copy");
+ }
+ virtual ~functor_t() throw() {
+ TRACE_DTOR(functor_t);
+ }
+ virtual value_t operator()(call_scope_t& args);
+ };
+
+ option_t<python_interpreter_t> * lookup_option(const char * p);
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
+
+ OPTION_(python_interpreter_t, import_, DO_(scope) {
+ interactive_t args(scope, "ss");
+ parent->import_option(args.get<string>(1));
+ });
+};
+
+extern shared_ptr<python_interpreter_t> python_session;
+
+} // namespace ledger
+
+#endif // HAVE_BOOST_PYTHON
+
+#endif // _PYINTERP_H
diff --git a/src/pyledger.cc b/src/pyledger.cc
new file mode 100644
index 00000000..cf7e1527
--- /dev/null
+++ b/src/pyledger.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "pyinterp.h"
+
+using namespace boost::python;
+
+namespace ledger {
+ extern void initialize_for_python();
+}
+
+BOOST_PYTHON_MODULE(ledger)
+{
+ using namespace ledger;
+
+ if (! python_session.get())
+ python_session.reset(new python_interpreter_t);
+
+ set_session_context(python_session.get());
+
+ initialize_for_python();
+}
diff --git a/src/pyutils.h b/src/pyutils.h
new file mode 100644
index 00000000..54d6fa28
--- /dev/null
+++ b/src/pyutils.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#ifndef _PY_UTILS_H
+#define _PY_UTILS_H
+
+template <typename T, typename TfromPy>
+struct object_from_python
+{
+ object_from_python() {
+ boost::python::converter::registry::insert
+ (&TfromPy::convertible, &TfromPy::construct,
+ boost::python::type_id<T>());
+ }
+};
+
+template <typename T, typename TtoPy, typename TfromPy>
+struct register_python_conversion
+{
+ register_python_conversion() {
+ boost::python::to_python_converter<T, TtoPy>();
+ object_from_python<T, TfromPy>();
+ }
+};
+
+template <typename T>
+struct register_optional_to_python : public boost::noncopyable
+{
+ struct optional_to_python
+ {
+ static PyObject * convert(const boost::optional<T>& value)
+ {
+ return boost::python::incref
+ (value ? boost::python::to_python_value<T>()(*value) :
+ boost::python::detail::none());
+ }
+ };
+
+ struct optional_from_python
+ {
+ static void * convertible(PyObject * source)
+ {
+ using namespace boost::python::converter;
+
+ if (source == Py_None)
+ return source;
+
+ const registration& converters(registered<T>::converters);
+
+ if (implicit_rvalue_convertible_from_python(source, converters)) {
+ rvalue_from_python_stage1_data data =
+ rvalue_from_python_stage1(source, converters);
+ return rvalue_from_python_stage2(source, data, converters);
+ }
+ return NULL;
+ }
+
+ static void construct(PyObject * source,
+ boost::python::converter::rvalue_from_python_stage1_data * data)
+ {
+ using namespace boost::python::converter;
+
+ void * const storage =
+ reinterpret_cast<rvalue_from_python_storage<T> *>(data)->storage.bytes;
+
+ if (data->convertible == source) // == None
+ new (storage) boost::optional<T>(); // A Boost uninitialized value
+ else
+ new (storage) boost::optional<T>(*reinterpret_cast<T *>(data->convertible));
+
+ data->convertible = storage;
+ }
+ };
+
+ explicit register_optional_to_python() {
+ register_python_conversion<boost::optional<T>,
+ optional_to_python, optional_from_python>();
+ }
+};
+
+template <typename T1, typename T2>
+struct PairToTupleConverter
+{
+ static PyObject * convert(const std::pair<T1, T2>& pair) {
+ return boost::python::incref
+ (boost::python::make_tuple(pair.first, pair.second).ptr());
+ }
+};
+
+template <typename MapType>
+struct map_value_type_converter
+{
+ map_value_type_converter() {
+ boost::python::to_python_converter
+ <typename MapType::value_type,
+ PairToTupleConverter<const typename MapType::key_type,
+ typename MapType::mapped_type> >();
+ }
+};
+
+template <typename T>
+PyObject * str_to_py_unicode(const T& str)
+{
+ using namespace boost::python;
+ PyObject * pstr = PyString_FromString(str.c_str());
+ PyObject * uni = PyUnicode_FromEncodedObject(pstr, "UTF-8", NULL);
+ return object(handle<>(borrowed(uni))).ptr();
+}
+
+namespace boost { namespace python {
+
+// Use expr to create the PyObject corresponding to x
+# define BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T, expr, pytype)\
+ template <> struct to_python_value<T&> \
+ : detail::builtin_to_python \
+ { \
+ inline PyObject* operator()(T const& x) const \
+ { \
+ return (expr); \
+ } \
+ inline PyTypeObject const* get_pytype() const \
+ { \
+ return (pytype); \
+ } \
+ }; \
+ template <> struct to_python_value<T const&> \
+ : detail::builtin_to_python \
+ { \
+ inline PyObject* operator()(T const& x) const \
+ { \
+ return (expr); \
+ } \
+ inline PyTypeObject const* get_pytype() const \
+ { \
+ return (pytype); \
+ } \
+ };
+
+# define BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T, expr) \
+ namespace converter \
+ { \
+ template <> struct arg_to_python< T > \
+ : handle<> \
+ { \
+ arg_to_python(T const& x) \
+ : python::handle<>(expr) {} \
+ }; \
+ }
+
+// Specialize argument and return value converters for T using expr
+# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr, pytype) \
+ BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T,expr, pytype) \
+ BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T,expr)
+
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(ledger::string, ::PyUnicode_FromEncodedObject(::PyString_FromString(x.c_str()), "UTF-8", NULL), &PyUnicode_Type)
+
+} } // namespace boost::python
+
+//boost::python::register_ptr_to_python< boost::shared_ptr<Base> >();
+
+#endif // _PY_UTILS_H
diff --git a/src/query.cc b/src/query.cc
new file mode 100644
index 00000000..cfa321b0
--- /dev/null
+++ b/src/query.cc
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "query.h"
+#include "op.h"
+
+namespace ledger {
+
+query_t::lexer_t::token_t query_t::lexer_t::next_token()
+{
+ if (token_cache.kind != token_t::UNKNOWN) {
+ token_t tok = token_cache;
+ token_cache = token_t();
+ return tok;
+ }
+
+ if (arg_i == arg_end) {
+ if (begin == end || ++begin == end) {
+ return token_t(token_t::END_REACHED);
+ } else {
+ arg_i = (*begin).as_string().begin();
+ arg_end = (*begin).as_string().end();
+ }
+ }
+
+ if (consume_next_arg) {
+ consume_next_arg = false;
+ arg_i = arg_end;
+ return token_t(token_t::TERM, (*begin).as_string());
+ }
+
+ resume:
+ bool consume_next = false;
+ switch (*arg_i) {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ if (++arg_i == arg_end)
+ return next_token();
+ goto resume;
+
+ case '/': {
+ string pat;
+ bool found_end_slash = false;
+ for (++arg_i; arg_i != arg_end; ++arg_i) {
+ if (*arg_i == '\\') {
+ if (++arg_i == arg_end)
+ throw_(parse_error, _("Unexpected '\\' at end of pattern"));
+ }
+ else if (*arg_i == '/') {
+ ++arg_i;
+ found_end_slash = true;
+ break;
+ }
+ pat.push_back(*arg_i);
+ }
+ if (! found_end_slash)
+ throw_(parse_error, _("Expected '/' at end of pattern"));
+ if (pat.empty())
+ throw_(parse_error, _("Match pattern is empty"));
+
+ return token_t(token_t::TERM, pat);
+ }
+
+ case '(': ++arg_i; return token_t(token_t::LPAREN);
+ case ')': ++arg_i; return token_t(token_t::RPAREN);
+ case '&': ++arg_i; return token_t(token_t::TOK_AND);
+ case '|': ++arg_i; return token_t(token_t::TOK_OR);
+ case '!': ++arg_i; return token_t(token_t::TOK_NOT);
+ case '@': ++arg_i; return token_t(token_t::TOK_PAYEE);
+ case '#': ++arg_i; return token_t(token_t::TOK_CODE);
+ case '%': ++arg_i; return token_t(token_t::TOK_META);
+ case '=': ++arg_i; return token_t(token_t::TOK_EQ);
+
+ case '\\':
+ consume_next = true;
+ ++arg_i;
+ // fall through...
+ default: {
+ string ident;
+ string::const_iterator beg = arg_i;
+ for (; arg_i != arg_end; ++arg_i) {
+ switch (*arg_i) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ if (! consume_whitespace)
+ goto test_ident;
+ else
+ ident.push_back(*arg_i);
+ break;
+ case '(':
+ case ')':
+ case '&':
+ case '|':
+ case '!':
+ case '@':
+ case '#':
+ case '%':
+ case '=':
+ if (! consume_next)
+ goto test_ident;
+ // fall through...
+ default:
+ ident.push_back(*arg_i);
+ break;
+ }
+ }
+ consume_whitespace = false;
+
+test_ident:
+ if (ident == "and")
+ return token_t(token_t::TOK_AND);
+ else if (ident == "or")
+ return token_t(token_t::TOK_OR);
+ else if (ident == "not")
+ return token_t(token_t::TOK_NOT);
+ else if (ident == "code")
+ return token_t(token_t::TOK_CODE);
+ else if (ident == "desc")
+ return token_t(token_t::TOK_PAYEE);
+ else if (ident == "payee")
+ return token_t(token_t::TOK_PAYEE);
+ else if (ident == "note")
+ return token_t(token_t::TOK_NOTE);
+ else if (ident == "tag")
+ return token_t(token_t::TOK_META);
+ else if (ident == "meta")
+ return token_t(token_t::TOK_META);
+ else if (ident == "data")
+ return token_t(token_t::TOK_META);
+ else if (ident == "show") {
+ // The "show" keyword is special, and separates a limiting predicate
+ // from a display predicate.
+ DEBUG("pred.show", "string = " << (*begin).as_string());
+ return token_t(token_t::END_REACHED);
+ }
+#if 0
+ // jww (2009-11-06): This is disabled for the time being.
+ else if (ident == "date") {
+ // The date keyword takes the whole of the next string as its argument.
+ consume_whitespace = true;
+ return token_t(token_t::TOK_DATE);
+ }
+#endif
+ else if (ident == "expr") {
+ // The expr keyword takes the whole of the next string as its argument.
+ consume_next_arg = true;
+ return token_t(token_t::TOK_EXPR);
+ }
+ else
+ return token_t(token_t::TERM, ident);
+ break;
+ }
+ }
+
+ return token_t(token_t::UNKNOWN);
+}
+
+void query_t::lexer_t::token_t::unexpected()
+{
+ kind_t prev_kind = kind;
+
+ kind = UNKNOWN;
+
+ switch (prev_kind) {
+ case END_REACHED:
+ throw_(parse_error, _("Unexpected end of expression"));
+ case TERM:
+ throw_(parse_error, _("Unexpected string '%1'") << *value);
+ default:
+ throw_(parse_error, _("Unexpected token '%1'") << symbol());
+ }
+}
+
+void query_t::lexer_t::token_t::expected(char wanted, char c)
+{
+ kind = UNKNOWN;
+
+ if (c == '\0' || c == -1) {
+ if (wanted == '\0' || wanted == -1)
+ throw_(parse_error, _("Unexpected end"));
+ else
+ throw_(parse_error, _("Missing '%1'") << wanted);
+ } else {
+ if (wanted == '\0' || wanted == -1)
+ throw_(parse_error, _("Invalid char '%1'") << c);
+ else
+ throw_(parse_error, _("Invalid char '%1' (wanted '%2')") << c << wanted);
+ }
+}
+
+expr_t::ptr_op_t
+query_t::parser_t::parse_query_term(query_t::lexer_t::token_t::kind_t tok_context)
+{
+ expr_t::ptr_op_t node;
+
+ lexer_t::token_t tok = lexer.next_token();
+ switch (tok.kind) {
+ case lexer_t::token_t::END_REACHED:
+ break;
+
+ case lexer_t::token_t::TOK_DATE:
+ case lexer_t::token_t::TOK_CODE:
+ case lexer_t::token_t::TOK_PAYEE:
+ case lexer_t::token_t::TOK_NOTE:
+ case lexer_t::token_t::TOK_ACCOUNT:
+ case lexer_t::token_t::TOK_META:
+ case lexer_t::token_t::TOK_EXPR:
+ node = parse_query_term(tok.kind);
+ if (! node)
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol());
+ break;
+
+ case lexer_t::token_t::TERM:
+ assert(tok.value);
+ switch (tok_context) {
+ case lexer_t::token_t::TOK_DATE: {
+ expr_t::ptr_op_t ident = new expr_t::op_t(expr_t::op_t::IDENT);
+ ident->set_ident("date");
+
+ date_interval_t interval(*tok.value);
+
+ if (interval.start) {
+ node = new expr_t::op_t(expr_t::op_t::O_GTE);
+ node->set_left(ident);
+
+ expr_t::ptr_op_t arg1 = new expr_t::op_t(expr_t::op_t::VALUE);
+ arg1->set_value(*interval.start);
+ node->set_right(arg1);
+ }
+
+ if (interval.finish) {
+ expr_t::ptr_op_t lt = new expr_t::op_t(expr_t::op_t::O_LT);
+ lt->set_left(ident);
+
+ expr_t::ptr_op_t arg1 = new expr_t::op_t(expr_t::op_t::VALUE);
+ arg1->set_value(*interval.finish);
+ lt->set_right(arg1);
+
+ if (node) {
+ expr_t::ptr_op_t prev(node);
+ node = new expr_t::op_t(expr_t::op_t::O_AND);
+ node->set_left(prev);
+ node->set_right(lt);
+ } else {
+ node = lt;
+ }
+ }
+ break;
+ }
+
+ case lexer_t::token_t::TOK_EXPR:
+ node = expr_t(*tok.value).get_op();
+ break;
+
+ case lexer_t::token_t::TOK_META: {
+ node = new expr_t::op_t(expr_t::op_t::O_CALL);
+
+ expr_t::ptr_op_t ident = new expr_t::op_t(expr_t::op_t::IDENT);
+ ident->set_ident("has_tag");
+ node->set_left(ident);
+
+ expr_t::ptr_op_t arg1 = new expr_t::op_t(expr_t::op_t::VALUE);
+ arg1->set_value(mask_t(*tok.value));
+
+ tok = lexer.peek_token();
+ if (tok.kind == lexer_t::token_t::TOK_EQ) {
+ tok = lexer.next_token();
+ tok = lexer.next_token();
+ if (tok.kind != lexer_t::token_t::TERM)
+ throw_(parse_error,
+ _("Metadata equality operator not followed by term"));
+
+ expr_t::ptr_op_t arg2 = new expr_t::op_t(expr_t::op_t::VALUE);
+ assert(tok.value);
+ arg2->set_value(mask_t(*tok.value));
+
+ node->set_right(expr_t::op_t::new_node
+ (expr_t::op_t::O_SEQ,
+ expr_t::op_t::new_node
+ (expr_t::op_t::O_CONS, arg1, arg2)));
+ } else {
+ node->set_right(arg1);
+ }
+ break;
+ }
+
+ default: {
+ node = new expr_t::op_t(expr_t::op_t::O_MATCH);
+
+ expr_t::ptr_op_t ident = new expr_t::op_t(expr_t::op_t::IDENT);
+ switch (tok_context) {
+ case lexer_t::token_t::TOK_ACCOUNT:
+ ident->set_ident("account"); break;
+ case lexer_t::token_t::TOK_PAYEE:
+ ident->set_ident("payee"); break;
+ case lexer_t::token_t::TOK_CODE:
+ ident->set_ident("code"); break;
+ case lexer_t::token_t::TOK_NOTE:
+ ident->set_ident("note"); break;
+ default:
+ assert(false); break;
+ }
+
+ expr_t::ptr_op_t mask = new expr_t::op_t(expr_t::op_t::VALUE);
+ DEBUG("query.mask", "Mask from string: " << *tok.value);
+ mask->set_value(mask_t(*tok.value));
+ DEBUG("query.mask", "Mask is: " << mask->as_value().as_mask().str());
+
+ node->set_left(ident);
+ node->set_right(mask);
+ }
+ }
+ break;
+
+ case lexer_t::token_t::LPAREN:
+ node = parse_query_expr(tok_context);
+ tok = lexer.next_token();
+ if (tok.kind != lexer_t::token_t::RPAREN)
+ tok.expected(')');
+ break;
+
+ default:
+ lexer.push_token(tok);
+ break;
+ }
+
+ return node;
+}
+
+expr_t::ptr_op_t
+query_t::parser_t::parse_unary_expr(lexer_t::token_t::kind_t tok_context)
+{
+ expr_t::ptr_op_t node;
+
+ lexer_t::token_t tok = lexer.next_token();
+ switch (tok.kind) {
+ case lexer_t::token_t::TOK_NOT: {
+ expr_t::ptr_op_t term(parse_query_term(tok_context));
+ if (! term)
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol());
+
+ node = new expr_t::op_t(expr_t::op_t::O_NOT);
+ node->set_left(term);
+ break;
+ }
+
+ default:
+ lexer.push_token(tok);
+ node = parse_query_term(tok_context);
+ break;
+ }
+
+ return node;
+}
+
+expr_t::ptr_op_t
+query_t::parser_t::parse_and_expr(lexer_t::token_t::kind_t tok_context)
+{
+ if (expr_t::ptr_op_t node = parse_unary_expr(tok_context)) {
+ while (true) {
+ lexer_t::token_t tok = lexer.next_token();
+ if (tok.kind == lexer_t::token_t::TOK_AND) {
+ expr_t::ptr_op_t prev(node);
+ node = new expr_t::op_t(expr_t::op_t::O_AND);
+ node->set_left(prev);
+ node->set_right(parse_unary_expr(tok_context));
+ if (! node->right())
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol());
+ } else {
+ lexer.push_token(tok);
+ break;
+ }
+ }
+ return node;
+ }
+ return expr_t::ptr_op_t();
+}
+
+expr_t::ptr_op_t
+query_t::parser_t::parse_or_expr(lexer_t::token_t::kind_t tok_context)
+{
+ if (expr_t::ptr_op_t node = parse_and_expr(tok_context)) {
+ while (true) {
+ lexer_t::token_t tok = lexer.next_token();
+ if (tok.kind == lexer_t::token_t::TOK_OR) {
+ expr_t::ptr_op_t prev(node);
+ node = new expr_t::op_t(expr_t::op_t::O_OR);
+ node->set_left(prev);
+ node->set_right(parse_and_expr(tok_context));
+ if (! node->right())
+ throw_(parse_error,
+ _("%1 operator not followed by argument") << tok.symbol());
+ } else {
+ lexer.push_token(tok);
+ break;
+ }
+ }
+ return node;
+ }
+ return expr_t::ptr_op_t();
+}
+
+expr_t::ptr_op_t
+query_t::parser_t::parse_query_expr(lexer_t::token_t::kind_t tok_context)
+{
+ if (expr_t::ptr_op_t node = parse_or_expr(tok_context)) {
+ if (expr_t::ptr_op_t next = parse_query_expr(tok_context)) {
+ expr_t::ptr_op_t prev(node);
+ node = new expr_t::op_t(expr_t::op_t::O_OR);
+ node->set_left(prev);
+ node->set_right(next);
+ }
+ return node;
+ }
+ return expr_t::ptr_op_t();
+}
+
+} // namespace ledger
diff --git a/src/query.h b/src/query.h
new file mode 100644
index 00000000..ebc14020
--- /dev/null
+++ b/src/query.h
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup expr
+ */
+
+/**
+ * @file predicate.h
+ * @author John Wiegley
+ *
+ * @ingroup expr
+ */
+#ifndef _QUERY_H
+#define _QUERY_H
+
+#include "predicate.h"
+
+namespace ledger {
+
+class query_t : public predicate_t
+{
+public:
+ class lexer_t
+ {
+ friend class query_t;
+ friend class parser_t;
+
+ value_t::sequence_t::const_iterator begin;
+ value_t::sequence_t::const_iterator end;
+
+ string::const_iterator arg_i;
+ string::const_iterator arg_end;
+
+ bool consume_whitespace;
+ bool consume_next_arg;
+
+ public:
+ struct token_t
+ {
+ enum kind_t {
+ UNKNOWN,
+
+ LPAREN,
+ RPAREN,
+
+ TOK_NOT,
+ TOK_AND,
+ TOK_OR,
+ TOK_EQ,
+
+ TOK_DATE,
+ TOK_CODE,
+ TOK_PAYEE,
+ TOK_NOTE,
+ TOK_ACCOUNT,
+ TOK_META,
+ TOK_EXPR,
+
+ TERM,
+
+ END_REACHED
+
+ } kind;
+
+ optional<string> value;
+
+ explicit token_t(kind_t _kind = UNKNOWN,
+ const optional<string>& _value = none)
+ : kind(_kind), value(_value) {
+ TRACE_CTOR(query_t::lexer_t::token_t, "");
+ }
+ token_t(const token_t& tok)
+ : kind(tok.kind), value(tok.value) {
+ TRACE_CTOR(query_t::lexer_t::token_t, "copy");
+ }
+ ~token_t() throw() {
+ TRACE_DTOR(query_t::lexer_t::token_t);
+ }
+
+ token_t& operator=(const token_t& tok) {
+ if (this != &tok) {
+ kind = tok.kind;
+ value = tok.value;
+ }
+ return *this;
+ }
+
+ operator bool() const {
+ return kind != END_REACHED;
+ }
+
+ string to_string() const {
+ switch (kind) {
+ case UNKNOWN: return "UNKNOWN";
+ case LPAREN: return "LPAREN";
+ case RPAREN: return "RPAREN";
+ case TOK_NOT: return "TOK_NOT";
+ case TOK_AND: return "TOK_AND";
+ case TOK_OR: return "TOK_OR";
+ case TOK_EQ: return "TOK_EQ";
+ case TOK_DATE: return "TOK_DATE";
+ case TOK_CODE: return "TOK_CODE";
+ case TOK_PAYEE: return "TOK_PAYEE";
+ case TOK_NOTE: return "TOK_NOTE";
+ case TOK_ACCOUNT: return "TOK_ACCOUNT";
+ case TOK_META: return "TOK_META";
+ case TOK_EXPR: return "TOK_EXPR";
+ case TERM: return string("TERM(") + *value + ")";
+ case END_REACHED: return "END_REACHED";
+ }
+ assert(false);
+ return empty_string;
+ }
+
+ string symbol() const {
+ switch (kind) {
+ case LPAREN: return "(";
+ case RPAREN: return ")";
+ case TOK_NOT: return "not";
+ case TOK_AND: return "and";
+ case TOK_OR: return "or";
+ case TOK_EQ: return "=";
+ case TOK_DATE: return "date";
+ case TOK_CODE: return "code";
+ case TOK_PAYEE: return "payee";
+ case TOK_NOTE: return "note";
+ case TOK_ACCOUNT: return "account";
+ case TOK_META: return "meta";
+ case TOK_EXPR: return "expr";
+
+ case END_REACHED: return "<EOF>";
+
+ case TERM:
+ assert(false);
+ return "<TERM>";
+
+ case UNKNOWN:
+ default:
+ assert(false);
+ return "<UNKNOWN>";
+ }
+ }
+
+ void unexpected();
+ void expected(char wanted, char c = '\0');
+ };
+
+ token_t token_cache;
+
+ lexer_t(value_t::sequence_t::const_iterator _begin,
+ value_t::sequence_t::const_iterator _end)
+ : begin(_begin), end(_end),
+ consume_whitespace(false),
+ consume_next_arg(false)
+ {
+ TRACE_CTOR(query_t::lexer_t, "");
+ assert(begin != end);
+ arg_i = (*begin).as_string().begin();
+ arg_end = (*begin).as_string().end();
+ }
+ lexer_t(const lexer_t& lexer)
+ : begin(lexer.begin), end(lexer.end),
+ arg_i(lexer.arg_i), arg_end(lexer.arg_end),
+ consume_whitespace(lexer.consume_whitespace),
+ consume_next_arg(lexer.consume_next_arg),
+ token_cache(lexer.token_cache)
+ {
+ TRACE_CTOR(query_t::lexer_t, "copy");
+ }
+ ~lexer_t() throw() {
+ TRACE_DTOR(query_t::lexer_t);
+ }
+
+ token_t next_token();
+ void push_token(token_t tok) {
+ assert(token_cache.kind == token_t::UNKNOWN);
+ token_cache = tok;
+ }
+ token_t peek_token() {
+ if (token_cache.kind == token_t::UNKNOWN)
+ token_cache = next_token();
+ return token_cache;
+ }
+ };
+
+protected:
+ class parser_t
+ {
+ friend class query_t;
+
+ value_t args;
+ lexer_t lexer;
+
+ expr_t::ptr_op_t parse_query_term(lexer_t::token_t::kind_t tok_context);
+ expr_t::ptr_op_t parse_unary_expr(lexer_t::token_t::kind_t tok_context);
+ expr_t::ptr_op_t parse_and_expr(lexer_t::token_t::kind_t tok_context);
+ expr_t::ptr_op_t parse_or_expr(lexer_t::token_t::kind_t tok_context);
+ expr_t::ptr_op_t parse_query_expr(lexer_t::token_t::kind_t tok_context);
+
+ public:
+ parser_t(const value_t& _args)
+ : args(_args), lexer(args.begin(), args.end()) {
+ TRACE_CTOR(query_t::parser_t, "");
+ }
+ parser_t(const parser_t& parser)
+ : args(parser.args), lexer(parser.lexer) {
+ TRACE_CTOR(query_t::parser_t, "copy");
+ }
+ ~parser_t() throw() {
+ TRACE_DTOR(query_t::parser_t);
+ }
+
+ expr_t::ptr_op_t parse() {
+ return parse_query_expr(lexer_t::token_t::TOK_ACCOUNT);
+ }
+
+ bool tokens_remaining() {
+ lexer_t::token_t tok = lexer.peek_token();
+ assert(tok.kind != lexer_t::token_t::UNKNOWN);
+ return tok.kind != lexer_t::token_t::END_REACHED;
+ }
+ };
+
+ optional<parser_t> parser;
+
+public:
+ query_t() {
+ TRACE_CTOR(query_t, "");
+ }
+ query_t(const query_t& other)
+ : predicate_t(other) {
+ TRACE_CTOR(query_t, "copy");
+ }
+ query_t(const string& arg,
+ const keep_details_t& _what_to_keep = keep_details_t())
+ : predicate_t(_what_to_keep) {
+ TRACE_CTOR(query_t, "string, keep_details_t");
+ if (! arg.empty()) {
+ value_t temp(string_value(arg));
+ parse_args(temp.to_sequence());
+ }
+ }
+ query_t(const value_t& args,
+ const keep_details_t& _what_to_keep = keep_details_t())
+ : predicate_t(_what_to_keep) {
+ TRACE_CTOR(query_t, "value_t, keep_details_t");
+ if (! args.empty())
+ parse_args(args);
+ }
+ virtual ~query_t() {
+ TRACE_DTOR(query_t);
+ }
+
+ void parse_args(const value_t& args) {
+ if (! parser)
+ parser = parser_t(args);
+ ptr = parser->parse(); // expr_t::ptr
+ }
+
+ void parse_again() {
+ assert(parser);
+ ptr = parser->parse(); // expr_t::ptr
+ }
+
+ bool tokens_remaining() {
+ return parser && parser->tokens_remaining();
+ }
+
+ virtual string text() {
+ return print_to_str();
+ }
+};
+
+} // namespace ledger
+
+#endif // _QUERY_H
diff --git a/src/quotes.cc b/src/quotes.cc
new file mode 100644
index 00000000..f892e93f
--- /dev/null
+++ b/src/quotes.cc
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "amount.h"
+#include "commodity.h"
+#include "pool.h"
+#include "quotes.h"
+
+namespace ledger {
+
+optional<price_point_t>
+commodity_quote_from_script(commodity_t& commodity,
+ const optional<commodity_t&>& exchange_commodity)
+{
+ DEBUG("commodity.download", "downloading quote for symbol " << commodity.symbol());
+#if defined(DEBUG_ON)
+ if (exchange_commodity)
+ DEBUG("commodity.download",
+ " in terms of commodity " << exchange_commodity->symbol());
+#endif
+
+ char buf[256];
+ buf[0] = '\0';
+
+ string getquote_cmd("getquote \"");
+ getquote_cmd += commodity.symbol();
+ getquote_cmd += "\" \"";
+ if (exchange_commodity)
+ getquote_cmd += exchange_commodity->symbol();
+ getquote_cmd += "\"";
+
+ DEBUG("commodity.download", "invoking command: " << getquote_cmd);
+
+ bool success = true;
+ if (FILE * fp = popen(getquote_cmd.c_str(), "r")) {
+ if (std::feof(fp) || ! std::fgets(buf, 255, fp))
+ success = false;
+ if (pclose(fp) != 0)
+ success = false;
+ } else {
+ success = false;
+ }
+
+ if (success && buf[0]) {
+ if (char * p = std::strchr(buf, '\n')) *p = '\0';
+ DEBUG("commodity.download", "downloaded quote: " << buf);
+
+ if (optional<std::pair<commodity_t *, price_point_t> > point =
+ commodity_pool_t::current_pool->parse_price_directive(buf)) {
+ if (commodity_pool_t::current_pool->price_db) {
+#if defined(__GNUG__) && __GNUG__ < 3
+ ofstream database(*commodity_pool_t::current_pool->price_db,
+ ios::out | ios::app);
+#else
+ ofstream database(*commodity_pool_t::current_pool->price_db,
+ std::ios_base::out | std::ios_base::app);
+#endif
+ database << "P "
+ << format_datetime(point->second.when, FMT_WRITTEN)
+ << " " << commodity.symbol()
+ << " " << point->second.price
+ << std::endl;
+ }
+ return point->second;
+ }
+ } else {
+ DEBUG("commodity.download",
+ "Failed to download price for '" << commodity.symbol() <<
+ "' (command: \"getquote " << commodity.symbol() <<
+ " " << (exchange_commodity ?
+ exchange_commodity->symbol() : "''") << "\")");
+
+ // Don't try to download this commodity again.
+ commodity.add_flags(COMMODITY_NOMARKET);
+ }
+ return none;
+}
+
+} // namespace ledger
diff --git a/src/quotes.h b/src/quotes.h
new file mode 100644
index 00000000..d00c5bfd
--- /dev/null
+++ b/src/quotes.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup extra
+ */
+
+/**
+ * @file quotes.h
+ * @author John Wiegley
+ *
+ * @ingroup extra
+ */
+#ifndef _QUOTES_H
+#define _QUOTES_H
+
+namespace ledger {
+
+optional<price_point_t>
+commodity_quote_from_script(commodity_t& commodity,
+ const optional<commodity_t&>& exchange_commodity);
+
+} // namespace ledger
+
+#endif // _QUOTES_H
diff --git a/src/report.cc b/src/report.cc
new file mode 100644
index 00000000..2d9d7cc6
--- /dev/null
+++ b/src/report.cc
@@ -0,0 +1,1307 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "report.h"
+#include "session.h"
+#include "pool.h"
+#include "format.h"
+#include "query.h"
+#include "output.h"
+#include "iterators.h"
+#include "filters.h"
+#include "precmd.h"
+#include "stats.h"
+#include "generate.h"
+#include "draft.h"
+#include "xml.h"
+#include "emacs.h"
+
+namespace ledger {
+
+void report_t::normalize_options(const string& verb)
+{
+ // Patch up some of the reporting options based on what kind of
+ // command it was.
+
+#ifdef HAVE_ISATTY
+ if (! HANDLED(force_color)) {
+ if (! HANDLED(no_color) && isatty(STDOUT_FILENO))
+ HANDLER(color).on_only(string("?normalize"));
+ if (HANDLED(color) && ! isatty(STDOUT_FILENO))
+ HANDLER(color).off();
+ }
+ if (! HANDLED(force_pager)) {
+ if (HANDLED(pager_) && ! isatty(STDOUT_FILENO))
+ HANDLER(pager_).off();
+ }
+#endif
+
+ item_t::use_effective_date = (HANDLED(effective) &&
+ ! HANDLED(actual_dates));
+
+ commodity_pool_t::current_pool->keep_base = HANDLED(base);
+ commodity_pool_t::current_pool->get_quotes = session.HANDLED(download);
+
+ if (session.HANDLED(price_exp_))
+ commodity_pool_t::current_pool->quote_leeway =
+ session.HANDLER(price_exp_).value.as_long();
+
+ if (session.HANDLED(price_db_))
+ commodity_pool_t::current_pool->price_db = session.HANDLER(price_db_).str();
+ else
+ commodity_pool_t::current_pool->price_db = none;
+
+ if (HANDLED(date_format_))
+ set_date_format(HANDLER(date_format_).str().c_str());
+ if (HANDLED(datetime_format_))
+ set_datetime_format(HANDLER(datetime_format_).str().c_str());
+ if (HANDLED(start_of_week_)) {
+ if (optional<date_time::weekdays> weekday =
+ string_to_day_of_week(HANDLER(start_of_week_).str()))
+ start_of_week = *weekday;
+ }
+
+ if (verb == "print" || verb == "xact" || verb == "dump") {
+ HANDLER(related).on_only(string("?normalize"));
+ HANDLER(related_all).on_only(string("?normalize"));
+ }
+ else if (verb == "equity") {
+ HANDLER(equity).on_only(string("?normalize"));
+ }
+
+ if (verb == "print")
+ HANDLER(limit_).on(string("?normalize"), "actual");
+
+ if (! HANDLED(empty))
+ HANDLER(display_).on(string("?normalize"), "amount|(!post&total)");
+
+ if (verb[0] != 'b' && verb[0] != 'r')
+ HANDLER(base).on_only(string("?normalize"));
+
+ // If a time period was specified with -p, check whether it also gave a
+ // begin and/or end to the report period (though these can be overridden
+ // using -b or -e). Then, if no _duration_ was specified (such as monthly),
+ // then ignore the period since the begin/end are the only interesting
+ // details.
+ if (HANDLED(period_)) {
+ if (! HANDLED(sort_all_))
+ HANDLER(sort_xacts_).on_only(string("?normalize"));
+
+ date_interval_t interval(HANDLER(period_).str());
+
+ optional<date_t> begin = interval.begin(session.current_year);
+ optional<date_t> end = interval.end(session.current_year);
+
+ if (! HANDLED(begin_) && begin) {
+ string predicate = "date>=[" + to_iso_extended_string(*begin) + "]";
+ HANDLER(limit_).on(string("?normalize"), predicate);
+ }
+ if (! HANDLED(end_) && end) {
+ string predicate = "date<[" + to_iso_extended_string(*end) + "]";
+ HANDLER(limit_).on(string("?normalize"), predicate);
+ }
+
+ if (! interval.duration)
+ HANDLER(period_).off();
+ }
+
+ // If -j or -J were specified, set the appropriate format string now so as
+ // to avoid option ordering issues were we to have done it during the
+ // initial parsing of the options.
+ if (HANDLED(amount_data)) {
+ HANDLER(format_)
+ .on_with(string("?normalize"), HANDLER(plot_amount_format_).value);
+ }
+ else if (HANDLED(total_data)) {
+ HANDLER(format_)
+ .on_with(string("?normalize"), HANDLER(plot_total_format_).value);
+ }
+
+ // If the --exchange (-X) option was used, parse out any final price
+ // settings that may be there.
+ if (HANDLED(exchange_) &&
+ HANDLER(exchange_).str().find('=') != string::npos) {
+ value_t(0L).exchange_commodities(HANDLER(exchange_).str(), true,
+ terminus);
+ }
+
+ long cols = 0;
+ if (HANDLED(columns_))
+ cols = HANDLER(columns_).value.to_long();
+ else if (const char * columns = std::getenv("COLUMNS"))
+ cols = lexical_cast<long>(columns);
+ else
+ cols = 80L;
+
+ if (cols > 0) {
+ DEBUG("auto.columns", "cols = " << cols);
+
+ if (! HANDLER(date_width_).specified)
+ HANDLER(date_width_)
+ .on_with(none, static_cast<long>(format_date(CURRENT_DATE(),
+ FMT_PRINTED).length()));
+
+ long date_width = HANDLER(date_width_).value.to_long();
+ long payee_width = (HANDLER(payee_width_).specified ?
+ HANDLER(payee_width_).value.to_long() :
+ int(double(cols) * 0.263157));
+ long account_width = (HANDLER(account_width_).specified ?
+ HANDLER(account_width_).value.to_long() :
+ int(double(cols) * 0.302631));
+ long amount_width = (HANDLER(amount_width_).specified ?
+ HANDLER(amount_width_).value.to_long() :
+ int(double(cols) * 0.157894));
+ long total_width = (HANDLER(total_width_).specified ?
+ HANDLER(total_width_).value.to_long() :
+ amount_width);
+
+ DEBUG("auto.columns", "date_width = " << date_width);
+ DEBUG("auto.columns", "payee_width = " << payee_width);
+ DEBUG("auto.columns", "account_width = " << account_width);
+ DEBUG("auto.columns", "amount_width = " << amount_width);
+ DEBUG("auto.columns", "total_width = " << total_width);
+
+ if (! HANDLER(date_width_).specified &&
+ ! HANDLER(payee_width_).specified &&
+ ! HANDLER(account_width_).specified &&
+ ! HANDLER(amount_width_).specified &&
+ ! HANDLER(total_width_).specified) {
+ long total = (4 /* the spaces between */ + date_width + payee_width +
+ account_width + amount_width + total_width);
+ if (total > cols) {
+ DEBUG("auto.columns", "adjusting account down");
+ account_width -= total - cols;
+ DEBUG("auto.columns", "account_width now = " << account_width);
+ }
+ }
+
+ if (! HANDLER(date_width_).specified)
+ HANDLER(date_width_).on_with(string("?normalize"), date_width);
+ if (! HANDLER(payee_width_).specified)
+ HANDLER(payee_width_).on_with(string("?normalize"), payee_width);
+ if (! HANDLER(account_width_).specified)
+ HANDLER(account_width_).on_with(string("?normalize"), account_width);
+ if (! HANDLER(amount_width_).specified)
+ HANDLER(amount_width_).on_with(string("?normalize"), amount_width);
+ if (! HANDLER(total_width_).specified)
+ HANDLER(total_width_).on_with(string("?normalize"), total_width);
+ }
+}
+
+void report_t::parse_query_args(const value_t& args, const string& whence)
+{
+ query_t query(args, what_to_keep());
+ if (query) {
+ HANDLER(limit_).on(whence, query.text());
+
+ DEBUG("report.predicate",
+ "Predicate = " << HANDLER(limit_).str());
+ }
+
+ if (query.tokens_remaining()) {
+ query.parse_again();
+ if (query) {
+ HANDLER(display_).on(whence, query.text());
+
+ DEBUG("report.predicate",
+ "Display predicate = " << HANDLER(display_).str());
+ }
+ }
+}
+
+void report_t::posts_report(post_handler_ptr handler)
+{
+ journal_posts_iterator walker(*session.journal.get());
+ pass_down_posts(chain_post_handlers(*this, handler), walker);
+ session.journal->clear_xdata();
+}
+
+void report_t::generate_report(post_handler_ptr handler)
+{
+ HANDLER(limit_).on(string("#generate"), "actual");
+
+ generate_posts_iterator walker
+ (session, HANDLED(seed_) ?
+ static_cast<unsigned int>(HANDLER(seed_).value.to_long()) : 0,
+ HANDLED(head_) ?
+ static_cast<unsigned int>(HANDLER(head_).value.to_long()) : 50);
+
+ pass_down_posts(chain_post_handlers(*this, handler), walker);
+}
+
+void report_t::xact_report(post_handler_ptr handler, xact_t& xact)
+{
+ xact_posts_iterator walker(xact);
+ pass_down_posts(chain_post_handlers(*this, handler), walker);
+ xact.clear_xdata();
+}
+
+void report_t::accounts_report(acct_handler_ptr handler)
+{
+ journal_posts_iterator walker(*session.journal.get());
+
+ // The lifetime of the chain object controls the lifetime of all temporary
+ // objects created within it during the call to pass_down_posts, which will
+ // be needed later by the pass_down_accounts.
+ post_handler_ptr chain =
+ chain_post_handlers(*this, post_handler_ptr(new ignore_posts), true);
+ pass_down_posts(chain, walker);
+
+ HANDLER(amount_).expr.mark_uncompiled();
+ HANDLER(total_).expr.mark_uncompiled();
+ HANDLER(display_amount_).expr.mark_uncompiled();
+ HANDLER(display_total_).expr.mark_uncompiled();
+ HANDLER(revalued_total_).expr.mark_uncompiled();
+
+ scoped_ptr<accounts_iterator> iter;
+ if (! HANDLED(sort_)) {
+ iter.reset(new basic_accounts_iterator(*session.journal->master));
+ } else {
+ expr_t sort_expr(HANDLER(sort_).str());
+ sort_expr.set_context(this);
+ iter.reset(new sorted_accounts_iterator(*session.journal->master,
+ sort_expr, HANDLED(flat)));
+ }
+
+ if (HANDLED(display_))
+ pass_down_accounts(handler, *iter.get(),
+ predicate_t(HANDLER(display_).str(), what_to_keep()),
+ *this);
+ else
+ pass_down_accounts(handler, *iter.get());
+
+ session.journal->clear_xdata();
+}
+
+void report_t::commodities_report(post_handler_ptr handler)
+{
+ posts_commodities_iterator walker(*session.journal.get());
+ pass_down_posts(chain_post_handlers(*this, handler), walker);
+ session.journal->clear_xdata();
+}
+
+value_t report_t::fn_amount_expr(call_scope_t& scope)
+{
+ return HANDLER(amount_).expr.calc(scope);
+}
+
+value_t report_t::fn_total_expr(call_scope_t& scope)
+{
+ return HANDLER(total_).expr.calc(scope);
+}
+
+value_t report_t::fn_display_amount(call_scope_t& scope)
+{
+ return HANDLER(display_amount_).expr.calc(scope);
+}
+
+value_t report_t::fn_display_total(call_scope_t& scope)
+{
+ return HANDLER(display_total_).expr.calc(scope);
+}
+
+value_t report_t::fn_market(call_scope_t& scope)
+{
+ interactive_t args(scope, "a&ts");
+
+ value_t result;
+ optional<datetime_t> moment = (args.has(1) ?
+ args.get<datetime_t>(1) :
+ optional<datetime_t>());
+ if (args.has(2))
+ result = args.value_at(0).exchange_commodities(args.get<string>(2),
+ /* add_prices= */ false,
+ moment);
+ else
+ result = args.value_at(0).value(true, moment);
+
+ if (! result.is_null())
+ return result;
+
+ return args.value_at(0);
+}
+
+value_t report_t::fn_get_at(call_scope_t& scope)
+{
+ interactive_t args(scope, "Sl");
+
+ DEBUG("report.get_at", "get_at[0] = " << args.value_at(0));
+ DEBUG("report.get_at", "get_at[1] = " << args.value_at(1));
+
+ if (args.get<long>(1) == 0) {
+ if (! args.value_at(0).is_sequence())
+ return args.value_at(0);
+ } else {
+ if (! args.value_at(0).is_sequence())
+ throw_(std::runtime_error,
+ _("Attempting to get argument at index %1 from %2")
+ << args.get<long>(1) << args.value_at(0).label());
+ }
+ return args.get<const value_t::sequence_t&>(0)[args.get<long>(1)];
+}
+
+value_t report_t::fn_is_seq(call_scope_t& scope)
+{
+ return scope.value().is_sequence();
+}
+
+value_t report_t::fn_strip(call_scope_t& args)
+{
+ return args.value().strip_annotations(what_to_keep());
+}
+
+value_t report_t::fn_trim(call_scope_t& args)
+{
+ string temp(args.value().to_string());
+ scoped_array<char> buf(new char[temp.length() + 1]);
+ std::strcpy(buf.get(), temp.c_str());
+
+ const char * p = buf.get();
+ while (*p && std::isspace(*p))
+ p++;
+
+ const char * e = buf.get() + temp.length();
+ while (e > p && std::isspace(*e))
+ e--;
+
+ if (e == p) {
+ return string_value(empty_string);
+ }
+ else if (e < p) {
+ assert(false);
+ return string_value(empty_string);
+ }
+ else {
+ return string_value(string(p, e - p));
+ }
+}
+
+value_t report_t::fn_scrub(call_scope_t& args)
+{
+ value_t temp(args.value().strip_annotations(what_to_keep()));
+ if (HANDLED(base))
+ return temp;
+ else
+ return temp.unreduced();
+}
+
+value_t report_t::fn_rounded(call_scope_t& args)
+{
+ return args.value().rounded();
+}
+
+value_t report_t::fn_unrounded(call_scope_t& args)
+{
+ return args.value().unrounded();
+}
+
+value_t report_t::fn_quantity(call_scope_t& scope)
+{
+ interactive_t args(scope, "a");
+ return args.get<amount_t>(0).number();
+}
+
+value_t report_t::fn_floor(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ return args.value_at(0).floored();
+}
+
+value_t report_t::fn_abs(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ return args.value_at(0).abs();
+}
+
+value_t report_t::fn_truncated(call_scope_t& scope)
+{
+ interactive_t args(scope, "v&ll");
+ return string_value(format_t::truncate
+ (args.get<string>(0),
+ args.has(1) && args.get<int>(1) > 0 ? args.get<int>(1) : 0,
+ args.has(2) ? args.get<int>(2) : 0));
+}
+
+value_t report_t::fn_justify(call_scope_t& scope)
+{
+ interactive_t args(scope, "vl&lbb");
+ std::ostringstream out;
+ args.value_at(0)
+ .print(out, args.get<int>(1),
+ args.has(2) ? args.get<int>(2) : -1,
+ args.has(3) ? args.get<bool>(3) : false,
+ args.has(4) ? args.get<bool>(4) : false);
+ return string_value(out.str());
+}
+
+value_t report_t::fn_quoted(call_scope_t& scope)
+{
+ interactive_t args(scope, "s");
+ std::ostringstream out;
+
+ out << '"';
+ foreach (const char ch, args.get<string>(0)) {
+ if (ch == '"')
+ out << "\\\"";
+ else
+ out << ch;
+ }
+ out << '"';
+
+ return string_value(out.str());
+}
+
+value_t report_t::fn_join(call_scope_t& scope)
+{
+ interactive_t args(scope, "s");
+ std::ostringstream out;
+
+ foreach (const char ch, args.get<string>(0)) {
+ if (ch != '\n')
+ out << ch;
+ else
+ out << "\\n";
+ }
+ return string_value(out.str());
+}
+
+value_t report_t::fn_format_date(call_scope_t& scope)
+{
+ interactive_t args(scope, "d&s");
+ if (args.has(1))
+ return string_value(format_date(args.get<date_t>(0), FMT_CUSTOM,
+ args.get<string>(1).c_str()));
+ else
+ return string_value(format_date(args.get<date_t>(0), FMT_PRINTED));
+}
+
+value_t report_t::fn_ansify_if(call_scope_t& scope)
+{
+ interactive_t args(scope, "v&s");
+
+ if (args.has(1)) {
+ string color = args.get<string>(1);
+ std::ostringstream buf;
+ if (color == "black") buf << "\033[30m";
+ else if (color == "red") buf << "\033[31m";
+ else if (color == "green") buf << "\033[32m";
+ else if (color == "yellow") buf << "\033[33m";
+ else if (color == "blue") buf << "\033[34m";
+ else if (color == "magenta") buf << "\033[35m";
+ else if (color == "cyan") buf << "\033[36m";
+ else if (color == "white") buf << "\033[37m";
+ else if (color == "bold") buf << "\033[1m";
+ else if (color == "underline") buf << "\033[4m";
+ else if (color == "blink") buf << "\033[5m";
+ buf << args.value_at(0);
+ buf << "\033[0m";
+ return string_value(buf.str());
+ } else {
+ return args.value_at(0);
+ }
+}
+
+value_t report_t::fn_percent(call_scope_t& scope)
+{
+ interactive_t args(scope, "aa");
+ return (amount_t("100.00%") *
+ (args.get<amount_t>(0) / args.get<amount_t>(1)).number());
+}
+
+value_t report_t::fn_price(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ return args.value_at(0).price();
+}
+
+value_t report_t::fn_lot_date(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ if (args.value_at(0).has_annotation()) {
+ const annotation_t& details(args.value_at(0).annotation());
+ if (details.date)
+ return *details.date;
+ }
+ return NULL_VALUE;
+}
+
+value_t report_t::fn_lot_price(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ if (args.value_at(0).has_annotation()) {
+ const annotation_t& details(args.value_at(0).annotation());
+ if (details.price)
+ return *details.price;
+ }
+ return NULL_VALUE;
+}
+
+value_t report_t::fn_lot_tag(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ if (args.value_at(0).has_annotation()) {
+ const annotation_t& details(args.value_at(0).annotation());
+ if (details.tag)
+ return string_value(*details.tag);
+ }
+ return NULL_VALUE;
+}
+
+value_t report_t::fn_to_boolean(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ args.value_at(0).in_place_cast(value_t::BOOLEAN);
+ return args.value_at(0);
+}
+
+value_t report_t::fn_to_int(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ args.value_at(0).in_place_cast(value_t::INTEGER);
+ return args.value_at(0);
+}
+
+value_t report_t::fn_to_datetime(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ args.value_at(0).in_place_cast(value_t::DATETIME);
+ return args.value_at(0);
+}
+
+value_t report_t::fn_to_date(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ args.value_at(0).in_place_cast(value_t::DATE);
+ return args.value_at(0);
+}
+
+value_t report_t::fn_to_amount(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ args.value_at(0).in_place_cast(value_t::AMOUNT);
+ return args.value_at(0);
+}
+
+value_t report_t::fn_to_balance(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ args.value_at(0).in_place_cast(value_t::BALANCE);
+ return args.value_at(0);
+}
+
+value_t report_t::fn_to_string(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ args.value_at(0).in_place_cast(value_t::STRING);
+ return args.value_at(0);
+}
+
+value_t report_t::fn_to_mask(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ args.value_at(0).in_place_cast(value_t::MASK);
+ return args.value_at(0);
+}
+
+value_t report_t::fn_to_sequence(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ args.value_at(0).in_place_cast(value_t::SEQUENCE);
+ return args.value_at(0);
+}
+
+namespace {
+ value_t fn_black(call_scope_t&) {
+ return string_value("black");
+ }
+ value_t fn_blink(call_scope_t&) {
+ return string_value("blink");
+ }
+ value_t fn_blue(call_scope_t&) {
+ return string_value("blue");
+ }
+ value_t fn_bold(call_scope_t&) {
+ return string_value("bold");
+ }
+ value_t fn_cyan(call_scope_t&) {
+ return string_value("cyan");
+ }
+ value_t fn_green(call_scope_t&) {
+ return string_value("green");
+ }
+ value_t fn_magenta(call_scope_t&) {
+ return string_value("magenta");
+ }
+ value_t fn_red(call_scope_t&) {
+ return string_value("red");
+ }
+ value_t fn_underline(call_scope_t&) {
+ return string_value("underline");
+ }
+ value_t fn_white(call_scope_t&) {
+ return string_value("white");
+ }
+ value_t fn_yellow(call_scope_t&) {
+ return string_value("yellow");
+ }
+ value_t fn_false(call_scope_t&) {
+ return false;
+ }
+ value_t fn_null(call_scope_t&) {
+ return NULL_VALUE;
+ }
+}
+
+value_t report_t::reload_command(call_scope_t&)
+{
+ session.close_journal_files();
+ session.read_journal_files();
+ return true;
+}
+
+value_t report_t::echo_command(call_scope_t& scope)
+{
+ interactive_t args(scope, "s");
+ std::ostream& out(output_stream);
+ out << args.get<string>(0) << std::endl;
+ return true;
+}
+
+option_t<report_t> * report_t::lookup_option(const char * p)
+{
+ switch (*p) {
+ case '%':
+ OPT_CH(percent);
+ break;
+ case 'A':
+ OPT_CH(average);
+ break;
+ case 'B':
+ OPT_CH(basis);
+ break;
+ case 'C':
+ OPT_CH(cleared);
+ break;
+ case 'D':
+ OPT_CH(daily);
+ break;
+ case 'E':
+ OPT_CH(empty);
+ break;
+ case 'F':
+ OPT_CH(format_);
+ break;
+ case 'G':
+ OPT_CH(gain);
+ break;
+ case 'I':
+ OPT_CH(price);
+ break;
+ case 'J':
+ OPT_CH(total_data);
+ break;
+ case 'L':
+ OPT_CH(actual);
+ break;
+ case 'M':
+ OPT_CH(monthly);
+ break;
+ case 'O':
+ OPT_CH(quantity);
+ break;
+ case 'P':
+ OPT_CH(by_payee);
+ break;
+ case 'R':
+ OPT_CH(real);
+ break;
+ case 'S':
+ OPT_CH(sort_);
+ break;
+ case 'T':
+ OPT_CH(total_);
+ break;
+ case 'U':
+ OPT_CH(uncleared);
+ break;
+ case 'V':
+ OPT_CH(market);
+ break;
+ case 'W':
+ OPT_CH(weekly);
+ break;
+ case 'X':
+ OPT_CH(exchange_);
+ break;
+ case 'Y':
+ OPT_CH(yearly);
+ break;
+ case 'a':
+ OPT(abbrev_len_);
+ else OPT_(account_);
+ else OPT(actual);
+ else OPT(actual_dates);
+ else OPT(add_budget);
+ else OPT(amount_);
+ else OPT(amount_data);
+ else OPT(anon);
+ else OPT_ALT(color, ansi);
+ else OPT(average);
+ else OPT(account_width_);
+ else OPT(amount_width_);
+ break;
+ case 'b':
+ OPT(balance_format_);
+ else OPT(base);
+ else OPT_ALT(basis, cost);
+ else OPT_(begin_);
+ else OPT(budget);
+ else OPT(by_payee);
+ break;
+ case 'c':
+ OPT(csv_format_);
+ else OPT(cleared);
+ else OPT(collapse);
+ else OPT(collapse_if_zero);
+ else OPT(color);
+ else OPT(columns_);
+ else OPT_ALT(basis, cost);
+ else OPT_(current);
+ break;
+ case 'd':
+ OPT(daily);
+ else OPT(date_);
+ else OPT(date_format_);
+ else OPT(datetime_format_);
+ else OPT(depth_);
+ else OPT(deviation);
+ else OPT_(display_);
+ else OPT(display_amount_);
+ else OPT(display_total_);
+ else OPT_ALT(dow, days-of-week);
+ else OPT(date_width_);
+ break;
+ case 'e':
+ OPT(effective);
+ else OPT(empty);
+ else OPT_(end_);
+ else OPT(equity);
+ else OPT(exact);
+ else OPT(exchange_);
+ break;
+ case 'f':
+ OPT(flat);
+ else OPT_ALT(forecast_while_, forecast_);
+ else OPT(forecast_years_);
+ else OPT(format_);
+ else OPT(force_color);
+ else OPT(force_pager);
+ else OPT_ALT(head_, first_);
+ break;
+ case 'g':
+ OPT(gain);
+ break;
+ case 'h':
+ OPT(head_);
+ break;
+ case 'i':
+ OPT(invert);
+ break;
+ case 'j':
+ OPT_CH(amount_data);
+ break;
+ case 'l':
+ OPT_(limit_);
+ else OPT(lot_dates);
+ else OPT(lot_prices);
+ else OPT(lot_tags);
+ else OPT(lots);
+ else OPT(lots_actual);
+ else OPT_ALT(tail_, last_);
+ break;
+ case 'm':
+ OPT(market);
+ else OPT(monthly);
+ break;
+ case 'n':
+ OPT_CH(collapse);
+ else OPT(no_color);
+ else OPT(no_total);
+ else OPT(now_);
+ break;
+ case 'o':
+ OPT(only_);
+ else OPT_(output_);
+ break;
+ case 'p':
+ OPT(pager_);
+ else OPT(payee_);
+ else OPT(pending);
+ else OPT(percent);
+ else OPT_(period_);
+ else OPT_ALT(sort_xacts_, period_sort_);
+ else OPT(plot_amount_format_);
+ else OPT(plot_total_format_);
+ else OPT(price);
+ else OPT(prices_format_);
+ else OPT(pricedb_format_);
+ else OPT(print_format_);
+ else OPT(payee_width_);
+ else OPT(prepend_format_);
+ break;
+ case 'q':
+ OPT(quantity);
+ else OPT(quarterly);
+ break;
+ case 'r':
+ OPT(raw);
+ else OPT(real);
+ else OPT(register_format_);
+ else OPT_(related);
+ else OPT(related_all);
+ else OPT(revalued);
+ else OPT(revalued_only);
+ else OPT(revalued_total_);
+ break;
+ case 's':
+ OPT(sort_);
+ else OPT(sort_all_);
+ else OPT(sort_xacts_);
+ else OPT_(subtotal);
+ else OPT(start_of_week_);
+ else OPT(seed_);
+ break;
+ case 't':
+ OPT_CH(amount_);
+ else OPT(tail_);
+ else OPT(total_);
+ else OPT(total_data);
+ else OPT(truncate_);
+ else OPT(total_width_);
+ break;
+ case 'u':
+ OPT(unbudgeted);
+ else OPT(uncleared);
+ else OPT(unrealized);
+ else OPT(unrealized_gains_);
+ else OPT(unrealized_losses_);
+ else OPT(unround);
+ else OPT(unsorted);
+ break;
+ case 'w':
+ OPT(weekly);
+ else OPT_(wide);
+ break;
+ case 'y':
+ OPT_CH(date_format_);
+ else OPT(yearly);
+ break;
+ }
+ return NULL;
+}
+
+void report_t::define(const symbol_t::kind_t kind, const string& name,
+ expr_t::ptr_op_t def)
+{
+ session.define(kind, name, def);
+}
+
+expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
+{
+ if (expr_t::ptr_op_t def = session.lookup(kind, name))
+ return def;
+
+ const char * p = name.c_str();
+
+ switch (kind) {
+ case symbol_t::FUNCTION:
+ // Support 2.x's single-letter value expression names.
+ if (*(p + 1) == '\0') {
+ switch (*p) {
+ case 'd':
+ case 'm':
+ return MAKE_FUNCTOR(report_t::fn_now);
+ case 'P':
+ return MAKE_FUNCTOR(report_t::fn_market);
+ case 't':
+ return MAKE_FUNCTOR(report_t::fn_display_amount);
+ case 'T':
+ return MAKE_FUNCTOR(report_t::fn_display_total);
+ case 'U':
+ return MAKE_FUNCTOR(report_t::fn_abs);
+ case 'S':
+ return MAKE_FUNCTOR(report_t::fn_strip);
+ case 'i':
+ throw_(std::runtime_error,
+ _("The i value expression variable is no longer supported"));
+ case 'A':
+ throw_(std::runtime_error,
+ _("The A value expression variable is no longer supported"));
+ case 'v':
+ case 'V':
+ throw_(std::runtime_error,
+ _("The V and v value expression variables are no longer supported"));
+ case 'I':
+ case 'B':
+ throw_(std::runtime_error,
+ _("The I and B value expression variables are no longer supported"));
+ case 'g':
+ case 'G':
+ throw_(std::runtime_error,
+ _("The G and g value expression variables are no longer supported"));
+ default:
+ return NULL;
+ }
+ }
+
+ switch (*p) {
+ case 'a':
+ if (is_eq(p, "amount_expr"))
+ return MAKE_FUNCTOR(report_t::fn_amount_expr);
+ else if (is_eq(p, "ansify_if"))
+ return MAKE_FUNCTOR(report_t::fn_ansify_if);
+ else if (is_eq(p, "abs"))
+ return MAKE_FUNCTOR(report_t::fn_abs);
+ break;
+
+ case 'b':
+ if (is_eq(p, "black"))
+ return WRAP_FUNCTOR(fn_black);
+ else if (is_eq(p, "blink"))
+ return WRAP_FUNCTOR(fn_blink);
+ else if (is_eq(p, "blue"))
+ return WRAP_FUNCTOR(fn_blue);
+ else if (is_eq(p, "bold"))
+ return WRAP_FUNCTOR(fn_bold);
+ break;
+
+ case 'c':
+ if (is_eq(p, "cyan"))
+ return WRAP_FUNCTOR(fn_cyan);
+ break;
+
+ case 'd':
+ if (is_eq(p, "display_amount"))
+ return MAKE_FUNCTOR(report_t::fn_display_amount);
+ else if (is_eq(p, "display_total"))
+ return MAKE_FUNCTOR(report_t::fn_display_total);
+ else if (is_eq(p, "date"))
+ return MAKE_FUNCTOR(report_t::fn_now);
+ break;
+
+ case 'f':
+ if (is_eq(p, "format_date"))
+ return MAKE_FUNCTOR(report_t::fn_format_date);
+ else if (is_eq(p, "floor"))
+ return MAKE_FUNCTOR(report_t::fn_floor);
+ break;
+
+ case 'g':
+ if (is_eq(p, "get_at"))
+ return MAKE_FUNCTOR(report_t::fn_get_at);
+ else if (is_eq(p, "green"))
+ return WRAP_FUNCTOR(fn_green);
+ break;
+
+ case 'i':
+ if (is_eq(p, "is_seq"))
+ return MAKE_FUNCTOR(report_t::fn_is_seq);
+ break;
+
+ case 'j':
+ if (is_eq(p, "justify"))
+ return MAKE_FUNCTOR(report_t::fn_justify);
+ else if (is_eq(p, "join"))
+ return MAKE_FUNCTOR(report_t::fn_join);
+ break;
+
+ case 'm':
+ if (is_eq(p, "market"))
+ return MAKE_FUNCTOR(report_t::fn_market);
+ else if (is_eq(p, "magenta"))
+ return WRAP_FUNCTOR(fn_magenta);
+ break;
+
+ case 'n':
+ if (is_eq(p, "null"))
+ return WRAP_FUNCTOR(fn_null);
+ else if (is_eq(p, "now"))
+ return MAKE_FUNCTOR(report_t::fn_now);
+ break;
+
+ case 'o':
+ if (is_eq(p, "options"))
+ return MAKE_FUNCTOR(report_t::fn_options);
+ break;
+
+ case 'p':
+ if (is_eq(p, "post"))
+ return WRAP_FUNCTOR(fn_false);
+ else if (is_eq(p, "percent"))
+ return MAKE_FUNCTOR(report_t::fn_percent);
+ else if (is_eq(p, "price"))
+ return MAKE_FUNCTOR(report_t::fn_price);
+ break;
+
+ case 'q':
+ if (is_eq(p, "quoted"))
+ return MAKE_FUNCTOR(report_t::fn_quoted);
+ else if (is_eq(p, "quantity"))
+ return MAKE_FUNCTOR(report_t::fn_quantity);
+ break;
+
+ case 'r':
+ if (is_eq(p, "rounded"))
+ return MAKE_FUNCTOR(report_t::fn_rounded);
+ else if (is_eq(p, "red"))
+ return WRAP_FUNCTOR(fn_red);
+ break;
+
+ case 's':
+ if (is_eq(p, "scrub"))
+ return MAKE_FUNCTOR(report_t::fn_scrub);
+ else if (is_eq(p, "strip"))
+ return MAKE_FUNCTOR(report_t::fn_strip);
+ break;
+
+ case 't':
+ if (is_eq(p, "truncated"))
+ return MAKE_FUNCTOR(report_t::fn_truncated);
+ else if (is_eq(p, "total_expr"))
+ return MAKE_FUNCTOR(report_t::fn_total_expr);
+ else if (is_eq(p, "today"))
+ return MAKE_FUNCTOR(report_t::fn_today);
+ else if (is_eq(p, "t"))
+ return MAKE_FUNCTOR(report_t::fn_display_amount);
+ else if (is_eq(p, "trim"))
+ return MAKE_FUNCTOR(report_t::fn_trim);
+ else if (is_eq(p, "to_boolean"))
+ return MAKE_FUNCTOR(report_t::fn_to_boolean);
+ else if (is_eq(p, "to_int"))
+ return MAKE_FUNCTOR(report_t::fn_to_int);
+ else if (is_eq(p, "to_datetime"))
+ return MAKE_FUNCTOR(report_t::fn_to_datetime);
+ else if (is_eq(p, "to_date"))
+ return MAKE_FUNCTOR(report_t::fn_to_date);
+ else if (is_eq(p, "to_amount"))
+ return MAKE_FUNCTOR(report_t::fn_to_amount);
+ else if (is_eq(p, "to_balance"))
+ return MAKE_FUNCTOR(report_t::fn_to_balance);
+ else if (is_eq(p, "to_string"))
+ return MAKE_FUNCTOR(report_t::fn_to_string);
+ else if (is_eq(p, "to_mask"))
+ return MAKE_FUNCTOR(report_t::fn_to_mask);
+ else if (is_eq(p, "to_sequence"))
+ return MAKE_FUNCTOR(report_t::fn_to_sequence);
+ break;
+
+ case 'T':
+ if (is_eq(p, "T"))
+ return MAKE_FUNCTOR(report_t::fn_display_total);
+ break;
+
+ case 'u':
+ if (is_eq(p, "underline"))
+ return WRAP_FUNCTOR(fn_underline);
+ else if (is_eq(p, "unrounded"))
+ return MAKE_FUNCTOR(report_t::fn_unrounded);
+ break;
+
+ case 'w':
+ if (is_eq(p, "white"))
+ return WRAP_FUNCTOR(fn_white);
+ break;
+
+ case 'y':
+ if (is_eq(p, "yellow"))
+ return WRAP_FUNCTOR(fn_yellow);
+ break;
+ }
+
+ // Check if they are trying to access an option's setting or value.
+ if (option_t<report_t> * handler = lookup_option(p))
+ return MAKE_OPT_FUNCTOR(report_t, handler);
+ break;
+
+ case symbol_t::OPTION:
+ if (option_t<report_t> * handler = lookup_option(p))
+ return MAKE_OPT_HANDLER(report_t, handler);
+ break;
+
+ case symbol_t::COMMAND:
+ switch (*p) {
+ case 'b':
+ if (*(p + 1) == '\0' || is_eq(p, "bal") || is_eq(p, "balance")) {
+ return expr_t::op_t::wrap_functor
+ (reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
+ (new format_accounts(*this, report_format(HANDLER(balance_format_)),
+ maybe_format(HANDLER(prepend_format_))),
+ *this, "#balance"));
+ }
+ else if (is_eq(p, "budget")) {
+ HANDLER(amount_).set_expr(string("#budget"), "(amount, 0)");
+
+ budget_flags |= BUDGET_WRAP_VALUES;
+ if (! (budget_flags & ~BUDGET_WRAP_VALUES))
+ budget_flags |= BUDGET_BUDGETED;
+
+ return expr_t::op_t::wrap_functor
+ (reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
+ (new format_accounts(*this, report_format(HANDLER(budget_format_)),
+ maybe_format(HANDLER(prepend_format_))),
+ *this, "#budget"));
+ }
+ break;
+
+ case 'c':
+ if (is_eq(p, "csv")) {
+ return WRAP_FUNCTOR
+ (reporter<>
+ (new format_posts(*this, report_format(HANDLER(csv_format_)),
+ maybe_format(HANDLER(prepend_format_))),
+ *this, "#csv"));
+ }
+ else if (is_eq(p, "cleared")) {
+ HANDLER(amount_).set_expr(string("#cleared"),
+ "(amount, cleared ? amount : 0)");
+
+ return expr_t::op_t::wrap_functor
+ (reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
+ (new format_accounts(*this, report_format(HANDLER(cleared_format_)),
+ maybe_format(HANDLER(prepend_format_))),
+ *this, "#cleared"));
+ }
+ break;
+
+ case 'e':
+ if (is_eq(p, "equity"))
+ return WRAP_FUNCTOR
+ (reporter<>
+ (new format_posts(*this, report_format(HANDLER(print_format_))),
+ *this, "#equity"));
+ else if (is_eq(p, "entry"))
+ return WRAP_FUNCTOR(xact_command);
+ else if (is_eq(p, "emacs"))
+ return WRAP_FUNCTOR
+ (reporter<>(new format_emacs_posts(output_stream), *this, "#emacs"));
+ else if (is_eq(p, "echo"))
+ return MAKE_FUNCTOR(report_t::echo_command);
+ break;
+
+ case 'p':
+ if (*(p + 1) == '\0' || is_eq(p, "print"))
+ return WRAP_FUNCTOR
+ (reporter<>
+ (new format_posts(*this, report_format(HANDLER(print_format_)),
+ HANDLED(raw)), *this, "#print"));
+ else if (is_eq(p, "prices"))
+ return expr_t::op_t::wrap_functor
+ (reporter<post_t, post_handler_ptr, &report_t::commodities_report>
+ (new format_posts(*this, report_format(HANDLER(prices_format_)),
+ maybe_format(HANDLER(prepend_format_))),
+ *this, "#prices"));
+ else if (is_eq(p, "pricedb"))
+ return expr_t::op_t::wrap_functor
+ (reporter<post_t, post_handler_ptr, &report_t::commodities_report>
+ (new format_posts(*this, report_format(HANDLER(pricedb_format_)),
+ maybe_format(HANDLER(prepend_format_))),
+ *this, "#pricedb"));
+ break;
+
+ case 'r':
+ if (*(p + 1) == '\0' || is_eq(p, "reg") || is_eq(p, "register"))
+ return WRAP_FUNCTOR
+ (reporter<>
+ (new format_posts(*this, report_format(HANDLER(register_format_)),
+ false, maybe_format(HANDLER(prepend_format_))),
+ *this, "#register"));
+ else if (is_eq(p, "reload"))
+ return MAKE_FUNCTOR(report_t::reload_command);
+ break;
+
+ case 's':
+ if (is_eq(p, "stats") || is_eq(p, "stat"))
+ return WRAP_FUNCTOR(report_statistics);
+ break;
+
+ case 'x':
+ if (is_eq(p, "xact"))
+ return WRAP_FUNCTOR(xact_command);
+ else if (is_eq(p, "xml"))
+ return WRAP_FUNCTOR(reporter<>(new format_xml(*this), *this, "#xml"));
+ break;
+ }
+ break;
+
+ case symbol_t::PRECOMMAND:
+ switch (*p) {
+ case 'a':
+ if (is_eq(p, "args"))
+ return WRAP_FUNCTOR(args_command);
+ break;
+ case 'e':
+ if (is_eq(p, "eval"))
+ return WRAP_FUNCTOR(eval_command);
+ break;
+ case 'f':
+ if (is_eq(p, "format"))
+ return WRAP_FUNCTOR(format_command);
+ break;
+ case 'g':
+ if (is_eq(p, "generate"))
+ return expr_t::op_t::wrap_functor
+ (reporter<post_t, post_handler_ptr, &report_t::generate_report>
+ (new format_posts(*this, report_format(HANDLER(print_format_)),
+ false), *this, "#generate"));
+ case 'p':
+ if (is_eq(p, "parse"))
+ return WRAP_FUNCTOR(parse_command);
+ else if (is_eq(p, "period"))
+ return WRAP_FUNCTOR(period_command);
+ break;
+ case 't':
+ if (is_eq(p, "template"))
+ return WRAP_FUNCTOR(template_command);
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+} // namespace ledger
diff --git a/src/report.h b/src/report.h
new file mode 100644
index 00000000..94d39215
--- /dev/null
+++ b/src/report.h
@@ -0,0 +1,958 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup report
+ */
+
+/**
+ * @file report.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _REPORT_H
+#define _REPORT_H
+
+#include "interactive.h"
+#include "expr.h"
+#include "query.h"
+#include "chain.h"
+#include "stream.h"
+#include "option.h"
+#include "commodity.h"
+#include "annotate.h"
+#include "session.h"
+#include "format.h"
+
+namespace ledger {
+
+class session_t;
+class xact_t;
+
+// These are the elements of any report:
+//
+// 1. Formatting string used for outputting the underlying ReportedType.
+//
+// 2. Handler object for the ReportedType. This is constructed using #1, or
+// else #1 is ignored completely. This handler object is also constructed
+// with the output stream that will be used during formatting.
+//
+// --- The details of #1 and #2 together represent the ItemHandler.
+//
+// 3. Mode of the report. Currently there are four modes:
+//
+// a. Posting or commodity iteration. In this mode, all the journal's
+// xacts, the postings of a specific xact, or all the journal's
+// commodities are walked. In the first two cases, it's the underlying
+// postings which are passed to #2; in the second case, each
+// commodity is passed to #2.
+//
+// b. Account iteration. This employs step 'a', but add a prologue and
+// epilogue to it. In the prologue it "sums" all account totals and
+// subtotals; in the epilogue it calls yet another handler whose job is
+// reporting (the handler used in 'a' is only for calculation).
+//
+// There is one variation on 'b' in which a "totals" line is also
+// displayed.
+//
+// c. Write journal. In this mode, a single function is called that output
+// the journal object as a textual file. #2 is used to print out each
+// posting in the journal.
+//
+// d. Dump binary file. This is just like 'c', except that it dumps out a
+// binary file and #2 is completely ignored.
+//
+// 4. For 'a' and 'b' in #3, there is a different iteration function called,
+// depending on whether we're iterating:
+//
+// a. The postings of an xact: walk_postings.
+// b. The xacts of a journal: walk_xacts.
+// c. The commodities of a journal: walk_commodities.
+//
+// 5. Finally, for the 'a' and 'b' reporting modes, there is a variant which
+// says that the formatter should be "flushed" after the entities are
+// iterated. This does not happen for the commodities iteration, however.
+
+class report_t : public scope_t
+{
+ report_t();
+
+public:
+ session_t& session;
+ output_stream_t output_stream;
+
+#define BUDGET_NO_BUDGET 0x00
+#define BUDGET_BUDGETED 0x01
+#define BUDGET_UNBUDGETED 0x02
+#define BUDGET_WRAP_VALUES 0x04
+
+ datetime_t terminus;
+ uint_least8_t budget_flags;
+
+ explicit report_t(session_t& _session)
+ : session(_session), terminus(CURRENT_TIME()),
+ budget_flags(BUDGET_NO_BUDGET) {}
+
+ virtual ~report_t() {
+ output_stream.close();
+ }
+
+ void normalize_options(const string& verb);
+ void parse_query_args(const value_t& args, const string& whence);
+
+ void posts_report(post_handler_ptr handler);
+ void generate_report(post_handler_ptr handler);
+ void xact_report(post_handler_ptr handler, xact_t& xact);
+ void accounts_report(acct_handler_ptr handler);
+ void commodities_report(post_handler_ptr handler);
+
+ value_t fn_amount_expr(call_scope_t& scope);
+ value_t fn_total_expr(call_scope_t& scope);
+ value_t fn_display_amount(call_scope_t& scope);
+ value_t fn_display_total(call_scope_t& scope);
+ value_t fn_market(call_scope_t& scope);
+ value_t fn_get_at(call_scope_t& scope);
+ value_t fn_is_seq(call_scope_t& scope);
+ value_t fn_strip(call_scope_t& scope);
+ value_t fn_trim(call_scope_t& scope);
+ value_t fn_scrub(call_scope_t& scope);
+ value_t fn_quantity(call_scope_t& scope);
+ value_t fn_rounded(call_scope_t& scope);
+ value_t fn_unrounded(call_scope_t& scope);
+ value_t fn_truncated(call_scope_t& scope);
+ value_t fn_floor(call_scope_t& scope);
+ value_t fn_abs(call_scope_t& scope);
+ value_t fn_justify(call_scope_t& scope);
+ value_t fn_quoted(call_scope_t& scope);
+ value_t fn_join(call_scope_t& scope);
+ value_t fn_format_date(call_scope_t& scope);
+ value_t fn_ansify_if(call_scope_t& scope);
+ value_t fn_percent(call_scope_t& scope);
+ value_t fn_price(call_scope_t& scope);
+ value_t fn_lot_date(call_scope_t& scope);
+ value_t fn_lot_price(call_scope_t& scope);
+ value_t fn_lot_tag(call_scope_t& scope);
+ value_t fn_to_boolean(call_scope_t& scope);
+ value_t fn_to_int(call_scope_t& scope);
+ value_t fn_to_datetime(call_scope_t& scope);
+ value_t fn_to_date(call_scope_t& scope);
+ value_t fn_to_amount(call_scope_t& scope);
+ value_t fn_to_balance(call_scope_t& scope);
+ value_t fn_to_string(call_scope_t& scope);
+ value_t fn_to_mask(call_scope_t& scope);
+ value_t fn_to_sequence(call_scope_t& scope);
+
+ value_t fn_now(call_scope_t&) {
+ return terminus;
+ }
+ value_t fn_today(call_scope_t&) {
+ return terminus.date();
+ }
+
+ value_t fn_options(call_scope_t&) {
+ return value_t(static_cast<scope_t *>(this));
+ }
+
+ string report_format(option_t<report_t>& option) {
+ if (HANDLED(format_))
+ return HANDLER(format_).str();
+ return option.str();
+ }
+
+ optional<string> maybe_format(option_t<report_t>& option) {
+ if (option)
+ return option.str();
+ return none;
+ }
+
+ value_t reload_command(call_scope_t&);
+ value_t echo_command(call_scope_t& scope);
+
+ keep_details_t what_to_keep() {
+ bool lots = HANDLED(lots) || HANDLED(lots_actual);
+ return keep_details_t(lots || HANDLED(lot_prices),
+ lots || HANDLED(lot_dates),
+ lots || HANDLED(lot_tags),
+ HANDLED(lots_actual));
+ }
+
+ void report_options(std::ostream& out)
+ {
+ HANDLER(abbrev_len_).report(out);
+ HANDLER(account_).report(out);
+ HANDLER(actual).report(out);
+ HANDLER(actual_dates).report(out);
+ HANDLER(add_budget).report(out);
+ HANDLER(amount_).report(out);
+ HANDLER(amount_data).report(out);
+ HANDLER(anon).report(out);
+ HANDLER(average).report(out);
+ HANDLER(balance_format_).report(out);
+ HANDLER(base).report(out);
+ HANDLER(basis).report(out);
+ HANDLER(begin_).report(out);
+ HANDLER(budget).report(out);
+ HANDLER(budget_format_).report(out);
+ HANDLER(by_payee).report(out);
+ HANDLER(cleared).report(out);
+ HANDLER(cleared_format_).report(out);
+ HANDLER(color).report(out);
+ HANDLER(collapse).report(out);
+ HANDLER(collapse_if_zero).report(out);
+ HANDLER(columns_).report(out);
+ HANDLER(csv_format_).report(out);
+ HANDLER(current).report(out);
+ HANDLER(daily).report(out);
+ HANDLER(date_).report(out);
+ HANDLER(date_format_).report(out);
+ HANDLER(datetime_format_).report(out);
+ HANDLER(depth_).report(out);
+ HANDLER(deviation).report(out);
+ HANDLER(display_).report(out);
+ HANDLER(display_amount_).report(out);
+ HANDLER(display_total_).report(out);
+ HANDLER(dow).report(out);
+ HANDLER(effective).report(out);
+ HANDLER(empty).report(out);
+ HANDLER(end_).report(out);
+ HANDLER(equity).report(out);
+ HANDLER(exact).report(out);
+ HANDLER(exchange_).report(out);
+ HANDLER(flat).report(out);
+ HANDLER(force_color).report(out);
+ HANDLER(force_pager).report(out);
+ HANDLER(forecast_while_).report(out);
+ HANDLER(forecast_years_).report(out);
+ HANDLER(format_).report(out);
+ HANDLER(gain).report(out);
+ HANDLER(head_).report(out);
+ HANDLER(invert).report(out);
+ HANDLER(limit_).report(out);
+ HANDLER(lot_dates).report(out);
+ HANDLER(lot_prices).report(out);
+ HANDLER(lot_tags).report(out);
+ HANDLER(lots).report(out);
+ HANDLER(lots_actual).report(out);
+ HANDLER(market).report(out);
+ HANDLER(monthly).report(out);
+ HANDLER(no_total).report(out);
+ HANDLER(now_).report(out);
+ HANDLER(only_).report(out);
+ HANDLER(output_).report(out);
+ HANDLER(pager_).report(out);
+ HANDLER(payee_).report(out);
+ HANDLER(pending).report(out);
+ HANDLER(percent).report(out);
+ HANDLER(period_).report(out);
+ HANDLER(plot_amount_format_).report(out);
+ HANDLER(plot_total_format_).report(out);
+ HANDLER(prepend_format_).report(out);
+ HANDLER(price).report(out);
+ HANDLER(prices_format_).report(out);
+ HANDLER(pricedb_format_).report(out);
+ HANDLER(print_format_).report(out);
+ HANDLER(quantity).report(out);
+ HANDLER(quarterly).report(out);
+ HANDLER(raw).report(out);
+ HANDLER(real).report(out);
+ HANDLER(register_format_).report(out);
+ HANDLER(related).report(out);
+ HANDLER(related_all).report(out);
+ HANDLER(revalued).report(out);
+ HANDLER(revalued_only).report(out);
+ HANDLER(revalued_total_).report(out);
+ HANDLER(seed_).report(out);
+ HANDLER(sort_).report(out);
+ HANDLER(sort_all_).report(out);
+ HANDLER(sort_xacts_).report(out);
+ HANDLER(start_of_week_).report(out);
+ HANDLER(subtotal).report(out);
+ HANDLER(tail_).report(out);
+ HANDLER(total_).report(out);
+ HANDLER(total_data).report(out);
+ HANDLER(truncate_).report(out);
+ HANDLER(unbudgeted).report(out);
+ HANDLER(uncleared).report(out);
+ HANDLER(unrealized).report(out);
+ HANDLER(unrealized_gains_).report(out);
+ HANDLER(unrealized_losses_).report(out);
+ HANDLER(unround).report(out);
+ HANDLER(unsorted).report(out);
+ HANDLER(weekly).report(out);
+ HANDLER(wide).report(out);
+ HANDLER(yearly).report(out);
+ HANDLER(date_width_).report(out);
+ HANDLER(payee_width_).report(out);
+ HANDLER(account_width_).report(out);
+ HANDLER(amount_width_).report(out);
+ HANDLER(total_width_).report(out);
+ }
+
+ option_t<report_t> * lookup_option(const char * p);
+
+ virtual void define(const symbol_t::kind_t kind, const string& name,
+ expr_t::ptr_op_t def);
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
+
+ /**
+ * Option handlers
+ */
+
+ OPTION__(report_t, abbrev_len_,
+ CTOR(report_t, abbrev_len_) { on_with(none, 2L); });
+ OPTION(report_t, account_);
+
+ OPTION_(report_t, actual, DO() { // -L
+ parent->HANDLER(limit_).on(string("--actual"), "actual");
+ });
+
+ OPTION(report_t, actual_dates);
+
+ OPTION_(report_t, add_budget, DO() {
+ parent->budget_flags |= BUDGET_BUDGETED | BUDGET_UNBUDGETED;
+ });
+
+ OPTION__
+ (report_t, amount_, // -t
+ expr_t expr;
+ CTOR(report_t, amount_) {
+ set_expr(none, "amount");
+ }
+ void set_expr(const optional<string>& whence, const string& str) {
+ expr = str;
+ on(whence, str);
+ }
+ DO_(args) {
+ set_expr(args[0].to_string(), args[1].to_string());
+ });
+
+ OPTION(report_t, amount_data); // -j
+ OPTION(report_t, anon);
+
+ OPTION_(report_t, average, DO() { // -A
+ parent->HANDLER(display_total_)
+ .set_expr(string("--average"), "total_expr/count");
+ });
+
+ OPTION__(report_t, balance_format_, CTOR(report_t, balance_format_) {
+ on(none,
+ "%(justify(scrub(display_total), 20, -1, true, color))"
+ " %(!options.flat ? depth_spacer : \"\")"
+ "%-(ansify_if(partial_account(options.flat), blue if color))\n%/"
+ "%$1\n%/"
+ "--------------------\n");
+ });
+
+ OPTION(report_t, base);
+
+ OPTION_(report_t, basis, DO() { // -B
+ parent->HANDLER(revalued).on_only(string("--basis"));
+ parent->HANDLER(amount_).set_expr(string("--basis"), "rounded(cost)");
+ });
+
+ OPTION_(report_t, begin_, DO_(args) { // -b
+ date_interval_t interval(args[1].to_string());
+ optional<date_t> begin = interval.begin(parent->session.current_year);
+ if (! begin)
+ throw_(std::invalid_argument,
+ _("Could not determine beginning of period '%1'")
+ << args[1].to_string());
+
+ string predicate = "date>=[" + to_iso_extended_string(*begin) + "]";
+ parent->HANDLER(limit_).on(string("--begin"), predicate);
+ });
+
+ OPTION_(report_t, budget, DO() {
+ parent->budget_flags |= BUDGET_BUDGETED;
+ });
+
+ OPTION__(report_t, budget_format_, CTOR(report_t, budget_format_) {
+ on(none,
+ "%(justify(scrub(get_at(total_expr, 0)), 12, -1, true, color))"
+ " %(justify(scrub(- get_at(total_expr, 1)), 12, "
+ " 12 + 1 + 12, true, color))"
+ " %(justify(scrub(get_at(total_expr, 1) + "
+ " get_at(total_expr, 0)), 12, "
+ " 12 + 1 + 12 + 1 + 12, true, color))"
+ " %(ansify_if("
+ " justify((get_at(total_expr, 1) ? "
+ " scrub((100% * get_at(total_expr, 0)) / "
+ " - get_at(total_expr, 1)) : 0), "
+ " 5, -1, true, false),"
+ " magenta if (color and get_at(total_expr, 1) and "
+ " (abs(quantity(get_at(total_expr, 0)) / "
+ " quantity(get_at(total_expr, 1))) >= 1))))"
+ " %(!options.flat ? depth_spacer : \"\")"
+ "%-(ansify_if(partial_account(options.flat), blue if color))\n"
+ "%/%$1 %$2 %$3 %$4\n%/"
+ "------------ ------------ ------------ -----\n");
+ });
+
+ OPTION(report_t, by_payee); // -P
+
+ OPTION_(report_t, cleared, DO() { // -C
+ parent->HANDLER(limit_).on(string("--cleared"), "cleared");
+ });
+
+ OPTION__(report_t, cleared_format_, CTOR(report_t, cleared_format_) {
+ on(none,
+ "%(justify(scrub(get_at(total_expr, 0)), 16, -1, true, color))"
+ " %(justify(scrub(get_at(total_expr, 1)), 16, -1, true, color))"
+ " %(latest_cleared ? format_date(latest_cleared) : \" \")"
+ " %(!options.flat ? depth_spacer : \"\")"
+ "%-(ansify_if(partial_account(options.flat), blue if color))\n%/"
+ "%$1 %$2 %$3\n%/"
+ "---------------- ---------------- ---------\n");
+ });
+
+ OPTION(report_t, color);
+
+ OPTION_(report_t, collapse, DO() { // -n
+ // Make sure that balance reports are collapsed too, but only apply it
+ // to account xacts
+ parent->HANDLER(display_).on(string("--collapse"), "post|depth<=1");
+ });
+
+ OPTION_(report_t, collapse_if_zero, DO() {
+ parent->HANDLER(collapse).on_only(string("--collapse-if-zero"));
+ });
+
+ OPTION(report_t, columns_);
+
+ OPTION__(report_t, csv_format_, CTOR(report_t, csv_format_) {
+ on(none,
+ "%(quoted(date)),"
+ "%(quoted(payee)),"
+ "%(quoted(account)),"
+ "%(quoted(scrub(display_amount))),"
+ "%(quoted(cleared ? \"*\" : (pending ? \"!\" : \"\"))),"
+ "%(quoted(code)),"
+ "%(quoted(join(note | xact.note)))\n");
+ });
+
+ OPTION_(report_t, current, DO() { // -c
+ parent->HANDLER(limit_).on(string("--current"), "date<=today");
+ });
+
+ OPTION_(report_t, daily, DO() { // -D
+ parent->HANDLER(period_).on(string("--daily"), "daily");
+ });
+
+ OPTION(report_t, date_);
+ OPTION(report_t, date_format_);
+ OPTION(report_t, datetime_format_);
+
+ OPTION_(report_t, depth_, DO_(scope) {
+ interactive_t args(scope, "sl");
+ parent->HANDLER(display_).on(string("--depth"),
+ string("depth<=") + args.get<string>(1));
+ });
+
+ OPTION_(report_t, deviation, DO() {
+ parent->HANDLER(display_total_)
+ .set_expr(string("--deviation"), "amount_expr-total_expr/count");
+ });
+
+ OPTION__
+ (report_t, display_, // -d
+ CTOR(report_t, display_) {}
+ virtual void on_with(const optional<string>& whence, const value_t& text) {
+ if (! handled)
+ option_t<report_t>::on_with(whence, text);
+ else
+ option_t<report_t>::on_with(whence,
+ string_value(string("(") + str() + ")&(" +
+ text.as_string() + ")"));
+ });
+
+ OPTION__
+ (report_t, display_amount_,
+ expr_t expr;
+ CTOR(report_t, display_amount_) {
+ set_expr(none, "amount_expr");
+ }
+ void set_expr(const optional<string>& whence, const string& str) {
+ expr = str;
+ on(whence, str);
+ }
+ DO_(args) {
+ set_expr(args[0].to_string(), args[1].to_string());
+ });
+
+ OPTION__
+ (report_t, display_total_,
+ expr_t expr;
+ CTOR(report_t, display_total_) {
+ set_expr(none, "total_expr");
+ }
+ void set_expr(const optional<string>& whence, const string& str) {
+ expr = str;
+ on(whence, str);
+ }
+ DO_(args) {
+ set_expr(args[0].to_string(), args[1].to_string());
+ });
+
+ OPTION(report_t, dow);
+ OPTION(report_t, effective);
+ OPTION(report_t, empty); // -E
+
+ OPTION_(report_t, end_, DO_(args) { // -e
+ date_interval_t interval(args[1].to_string());
+ // Use begin() here so that if the user says --end=2008, we end on
+ // 2008/01/01 instead of 2009/01/01 (which is what end() would return).
+ optional<date_t> end = interval.begin(parent->session.current_year);
+ if (! end)
+ throw_(std::invalid_argument,
+ _("Could not determine end of period '%1'")
+ << args[1].to_string());
+
+ string predicate = "date<[" + to_iso_extended_string(*end) + "]";
+ parent->HANDLER(limit_).on(string("--end"), predicate);
+
+ parent->terminus = datetime_t(*end);
+ });
+
+ OPTION(report_t, equity);
+ OPTION(report_t, exact);
+
+ OPTION_(report_t, exchange_, DO_(args) { // -X
+ on_with(args[0].as_string(), args[1]);
+ call_scope_t no_args(*parent);
+ no_args.push_back(args[0]);
+ parent->HANDLER(market).parent = parent;
+ parent->HANDLER(market).handler(no_args);
+ });
+
+ OPTION(report_t, flat);
+ OPTION(report_t, force_color);
+ OPTION(report_t, force_pager);
+ OPTION(report_t, forecast_while_);
+ OPTION(report_t, forecast_years_);
+ OPTION(report_t, format_); // -F
+
+ OPTION_(report_t, gain, DO() { // -G
+ parent->HANDLER(revalued).on_only(string("--gain"));
+ parent->HANDLER(amount_).set_expr(string("--gain"), "(amount, cost)");
+ // Since we are displaying the amounts of revalued postings, they
+ // will end up being composite totals, and hence a pair of pairs.
+ parent->HANDLER(display_amount_)
+ .set_expr(string("--gain"),
+ "use_direct_amount ? amount :"
+ " (is_seq(get_at(amount_expr, 0)) ?"
+ " get_at(get_at(amount_expr, 0), 0) :"
+ " market(get_at(amount_expr, 0), date, exchange)"
+ " - get_at(amount_expr, 1))");
+ parent->HANDLER(revalued_total_)
+ .set_expr(string("--gain"),
+ "(market(get_at(total_expr, 0), date, exchange), "
+ "get_at(total_expr, 1))");
+ parent->HANDLER(display_total_)
+ .set_expr(string("--gain"),
+ "use_direct_amount ? total_expr :"
+ " market(get_at(total_expr, 0), date, exchange)"
+ " - get_at(total_expr, 1)");
+ });
+
+ OPTION(report_t, head_);
+
+ OPTION_(report_t, invert, DO() {
+ parent->HANDLER(amount_).set_expr(string("--invert"), "-amount");
+ });
+
+ OPTION__
+ (report_t, limit_, // -l
+ CTOR(report_t, limit_) {}
+ virtual void on_with(const optional<string>& whence, const value_t& text) {
+ if (! handled)
+ option_t<report_t>::on_with(whence, text);
+ else
+ option_t<report_t>::on_with(whence,
+ string_value(string("(") + str() + ")&(" +
+ text.as_string() + ")"));
+ });
+
+ OPTION(report_t, lot_dates);
+ OPTION(report_t, lot_prices);
+ OPTION(report_t, lot_tags);
+ OPTION(report_t, lots);
+ OPTION(report_t, lots_actual);
+
+ OPTION_(report_t, market, DO() { // -V
+ parent->HANDLER(revalued).on_only(string("--market"));
+ parent->HANDLER(display_amount_)
+ .set_expr(string("--market"), "market(amount_expr, date, exchange)");
+ parent->HANDLER(display_total_)
+ .set_expr(string("--market"), "market(total_expr, date, exchange)");
+ });
+
+ OPTION_(report_t, monthly, DO() { // -M
+ parent->HANDLER(period_).on(string("--monthly"), "monthly");
+ });
+
+ OPTION_(report_t, no_color, DO() {
+ parent->HANDLER(color).off();
+ });
+
+ OPTION(report_t, no_total);
+
+ OPTION_(report_t, now_, DO_(args) {
+ date_interval_t interval(args[1].to_string());
+ optional<date_t> begin = interval.begin(parent->session.current_year);
+ if (! begin)
+ throw_(std::invalid_argument,
+ _("Could not determine beginning of period '%1'")
+ << args[1].to_string());
+ ledger::epoch = parent->terminus = datetime_t(*begin);
+ parent->session.current_year = ledger::epoch->date().year();
+ });
+
+ OPTION__
+ (report_t, only_,
+ CTOR(report_t, only_) {}
+ virtual void on_with(const optional<string>& whence, const value_t& text) {
+ if (! handled)
+ option_t<report_t>::on_with(whence, text);
+ else
+ option_t<report_t>::on_with(whence,
+ string_value(string("(") + str() + ")&(" +
+ text.as_string() + ")"));
+ });
+
+ OPTION(report_t, output_); // -o
+
+#ifdef HAVE_ISATTY
+ OPTION__
+ (report_t, pager_,
+ CTOR(report_t, pager_) {
+ if (! std::getenv("PAGER") && isatty(STDOUT_FILENO)) {
+ bool have_less = false;
+ if (exists(path("/opt/local/bin/less")) ||
+ exists(path("/usr/local/bin/less")) ||
+ exists(path("/usr/bin/less")))
+ have_less = true;
+
+ if (have_less) {
+ on(none, "less");
+ setenv("LESS", "-FRSX", 0); // don't overwrite
+ }
+ }
+ }
+ virtual void on_with(const optional<string>& whence, const value_t& text) {
+ string cmd(text.to_string());
+ if (cmd == "" || cmd == "false" || cmd == "off" ||
+ cmd == "none" || cmd == "no" || cmd == "disable")
+ option_t<report_t>::off();
+ else
+ option_t<report_t>::on_with(whence, text);
+ });
+#else // HAVE_ISATTY
+ OPTION__
+ (report_t, pager_,
+ CTOR(report_t, pager_) {
+ }
+ virtual void on_with(const optional<string>& whence, const value_t& text) {
+ string cmd(text.to_string());
+ if (cmd == "" || cmd == "false" || cmd == "off" ||
+ cmd == "none" || cmd == "no" || cmd == "disable")
+ option_t<report_t>::off();
+ else
+ option_t<report_t>::on_with(whence, text);
+ });
+#endif // HAVE_ISATTY
+
+ OPTION(report_t, payee_);
+
+ OPTION_(report_t, pending, DO() { // -C
+ parent->HANDLER(limit_).on(string("--pending"), "pending");
+ });
+
+ OPTION_(report_t, percent, DO() { // -%
+ parent->HANDLER(total_)
+ .set_expr(string("--percent"),
+ "is_account&parent&parent.total&percent(total, parent.total)");
+ });
+
+ OPTION__
+ (report_t, period_, // -p
+ CTOR(report_t, period_) {}
+ virtual void on_with(const optional<string>& whence, const value_t& text) {
+ if (! handled)
+ option_t<report_t>::on_with(whence, text);
+ else
+ option_t<report_t>::on_with(whence,
+ string_value(text.as_string() + " " + str()));
+ });
+
+ OPTION__(report_t, plot_amount_format_, CTOR(report_t, plot_amount_format_) {
+ on(none,
+ "%(format_date(date, \"%Y-%m-%d\")) %(quantity(scrub(display_amount)))\n");
+ });
+
+ OPTION__(report_t, plot_total_format_, CTOR(report_t, plot_total_format_) {
+ on(none,
+ "%(format_date(date, \"%Y-%m-%d\")) %(quantity(scrub(display_total)))\n");
+ });
+
+ OPTION(report_t, prepend_format_);
+
+ OPTION_(report_t, price, DO() { // -I
+ parent->HANDLER(display_amount_)
+ .set_expr(string("--price"), "price(amount_expr)");
+ parent->HANDLER(display_total_)
+ .set_expr(string("--price"), "price(total_expr)");
+ });
+
+ OPTION__(report_t, prices_format_, CTOR(report_t, prices_format_) {
+ on(none,
+ "%(date) %-8(account) %(justify(scrub(display_amount), 12, "
+ " 2 + 9 + 8 + 12, true, color))\n");
+ });
+
+ OPTION__(report_t, pricedb_format_, CTOR(report_t, pricedb_format_) {
+ on(none,
+ "P %(datetime) %(account) %(scrub(display_amount))\n");
+ });
+
+ OPTION__(report_t, print_format_, CTOR(report_t, print_format_) {
+ on(none,
+ "%(xact.date)"
+ "%(!effective & xact.effective_date ?"
+ " \"=\" + xact.effective_date : \"\")"
+ "%(xact.cleared ? \" *\" : (xact.pending ? \" !\" : \"\"))"
+ "%(code ? \" (\" + code + \")\" :"
+ " \"\") %(payee)%(xact.comment)\n"
+ " %(xact.uncleared ?"
+ " (cleared ? \"* \" : (pending ? \"! \" : \"\")) : \"\")"
+ "%(calculated ? account : justify(account, 34, -1, false))"
+ "%(calculated ? \"\" : \" \" + justify(scrub(amount), 12, -1, true))"
+ "%(has_cost & !cost_calculated ?"
+ " \" @ \" + justify(scrub(abs(cost / amount)), 0) : \"\")"
+ "%(comment)\n%/"
+ " %$7%$8%$9%$A%$B\n%/\n");
+ });
+
+ OPTION_(report_t, quantity, DO() { // -O
+ parent->HANDLER(revalued).off();
+ parent->HANDLER(amount_).set_expr(string("--quantity"), "amount");
+ parent->HANDLER(total_).set_expr(string("--quantity"), "total");
+ });
+
+ OPTION_(report_t, quarterly, DO() {
+ parent->HANDLER(period_).on(string("--quarterly"), "quarterly");
+ });
+
+ OPTION(report_t, raw);
+
+ OPTION_(report_t, real, DO() { // -R
+ parent->HANDLER(limit_).on(string("--real"), "real");
+ });
+
+ OPTION__(report_t, register_format_, CTOR(report_t, register_format_) {
+ on(none,
+ "%(ansify_if(justify(format_date(date), date_width), green "
+ " if color & date > today))"
+ " %(ansify_if(justify(truncated(payee, payee_width), payee_width), "
+ " bold if color & !cleared & actual))"
+ " %(ansify_if(justify(truncated(account, account_width, abbrev_len), "
+ " account_width), blue if color))"
+ " %(justify(scrub(display_amount), amount_width, "
+ " 3 + date_width + payee_width + account_width + amount_width, "
+ " true, color))"
+ " %(justify(scrub(display_total), total_width, "
+ " 4 + date_width + payee_width + account_width + amount_width "
+ " + total_width, true, color))\n%/"
+ "%(justify(\" \", 2 + date_width + payee_width))%$3 %$4 %$5\n");
+ });
+
+ OPTION(report_t, related); // -r
+
+ OPTION_(report_t, related_all, DO() {
+ parent->HANDLER(related).on_only(string("--related-all"));
+ });
+
+ OPTION(report_t, revalued);
+ OPTION(report_t, revalued_only);
+
+ OPTION__
+ (report_t, revalued_total_,
+ expr_t expr;
+ CTOR(report_t, revalued_total_) {}
+ void set_expr(const optional<string>& whence, const string& str) {
+ expr = str;
+ on(whence, str);
+ }
+ DO_(args) {
+ set_expr(args[0].to_string(), args[1].to_string());
+ });
+
+ OPTION(report_t, seed_);
+
+ OPTION_(report_t, sort_, DO_(args) { // -S
+ on_with(args[0].as_string(), args[1]);
+ parent->HANDLER(sort_xacts_).off();
+ parent->HANDLER(sort_all_).off();
+ });
+
+ OPTION_(report_t, sort_all_, DO_(args) {
+ parent->HANDLER(sort_).on_with(string("--sort-all"), args[1]);
+ parent->HANDLER(sort_xacts_).off();
+ });
+
+ OPTION_(report_t, sort_xacts_, DO_(args) {
+ parent->HANDLER(sort_).on_with(string("--sort-xacts"), args[1]);
+ parent->HANDLER(sort_all_).off();
+ });
+
+ OPTION(report_t, start_of_week_);
+ OPTION(report_t, subtotal); // -s
+ OPTION(report_t, tail_);
+
+ OPTION__
+ (report_t, total_, // -T
+ expr_t expr;
+ CTOR(report_t, total_) {
+ set_expr(none, "total");
+ }
+ void set_expr(const optional<string>& whence, const string& str) {
+ expr = str;
+ on(whence, str);
+ }
+ DO_(args) {
+ set_expr(args[0].to_string(), args[1].to_string());
+ });
+
+ OPTION(report_t, total_data); // -J
+
+ OPTION_(report_t, truncate_, DO_(args) {
+ string style(args[1].to_string());
+ if (style == "leading")
+ format_t::default_style = format_t::TRUNCATE_LEADING;
+ else if (style == "middle")
+ format_t::default_style = format_t::TRUNCATE_MIDDLE;
+ else if (style == "trailing")
+ format_t::default_style = format_t::TRUNCATE_TRAILING;
+ else
+ throw_(std::invalid_argument,
+ _("Unrecognized truncation style: '%1'") << style);
+ format_t::default_style_changed = true;
+ });
+
+ OPTION_(report_t, unbudgeted, DO() {
+ parent->budget_flags |= BUDGET_UNBUDGETED;
+ });
+
+ OPTION_(report_t, uncleared, DO() { // -U
+ parent->HANDLER(limit_).on(string("--uncleared"), "uncleared|pending");
+ });
+
+ OPTION(report_t, unrealized);
+
+ OPTION(report_t, unrealized_gains_);
+ OPTION(report_t, unrealized_losses_);
+
+ OPTION_(report_t, unround, DO() {
+ parent->HANDLER(display_amount_)
+ .set_expr(string("--unround"), "unrounded(amount_expr)");
+ parent->HANDLER(display_total_)
+ .set_expr(string("--unround"), "unrounded(total_expr)");
+ });
+
+ OPTION(report_t, unsorted);
+
+ OPTION_(report_t, weekly, DO() { // -W
+ parent->HANDLER(period_).on(string("--weekly"), "weekly");
+ });
+
+ OPTION_(report_t, wide, DO() { // -w
+ parent->HANDLER(columns_).on_with(string("--wide"), 132L);
+ });
+
+ OPTION_(report_t, yearly, DO() { // -Y
+ parent->HANDLER(period_).on(string("--yearly"), "yearly");
+ });
+
+ OPTION__(report_t, date_width_,
+ bool specified;
+ CTOR(report_t, date_width_) { specified = false; }
+ DO_(args) { value = args[1].to_long(); specified = true; });
+ OPTION__(report_t, payee_width_,
+ bool specified;
+ CTOR(report_t, payee_width_) { specified = false; }
+ DO_(args) { value = args[1].to_long(); specified = true; });
+ OPTION__(report_t, account_width_,
+ bool specified;
+ CTOR(report_t, account_width_) { specified = false; }
+ DO_(args) { value = args[1].to_long(); specified = true; });
+ OPTION__(report_t, amount_width_,
+ bool specified;
+ CTOR(report_t, amount_width_) { specified = false; }
+ DO_(args) { value = args[1].to_long(); specified = true; });
+ OPTION__(report_t, total_width_,
+ bool specified;
+ CTOR(report_t, total_width_) { specified = false; }
+ DO_(args) { value = args[1].to_long(); specified = true; });
+};
+
+
+template <class Type = post_t,
+ class handler_ptr = post_handler_ptr,
+ void (report_t::*report_method)(handler_ptr) =
+ &report_t::posts_report>
+class reporter
+{
+ shared_ptr<item_handler<Type> > handler;
+
+ report_t& report;
+ string whence;
+
+public:
+ reporter(item_handler<Type> * _handler,
+ report_t& _report, const string& _whence)
+ : handler(_handler), report(_report), whence(_whence) {}
+
+ value_t operator()(call_scope_t& args)
+ {
+ if (args.size() > 0)
+ report.parse_query_args(args.value(), whence);
+
+ (report.*report_method)(handler_ptr(handler));
+
+ return true;
+ }
+};
+
+} // namespace ledger
+
+#endif // _REPORT_H
diff --git a/src/scope.cc b/src/scope.cc
new file mode 100644
index 00000000..64736ca3
--- /dev/null
+++ b/src/scope.cc
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "scope.h"
+
+namespace ledger {
+
+scope_t * scope_t::default_scope = NULL;
+
+void symbol_scope_t::define(const symbol_t::kind_t kind,
+ const string& name, expr_t::ptr_op_t def)
+{
+ DEBUG("scope.symbols", "Defining '" << name << "' = " << def);
+
+ if (! symbols)
+ symbols = symbol_map();
+
+ std::pair<symbol_map::iterator, bool> result
+ = symbols->insert(symbol_map::value_type(symbol_t(kind, name, def), def));
+ if (! result.second) {
+ symbol_map::iterator i = symbols->find(symbol_t(kind, name));
+ assert(i != symbols->end());
+ symbols->erase(i);
+
+ result = symbols->insert(symbol_map::value_type(symbol_t(kind, name, def),
+ def));
+ if (! result.second)
+ throw_(compile_error,
+ _("Redefinition of '%1' in the same scope") << name);
+ }
+}
+
+expr_t::ptr_op_t symbol_scope_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
+{
+ if (symbols) {
+ symbol_map::const_iterator i = symbols->find(symbol_t(kind, name));
+ if (i != symbols->end())
+ return (*i).second;
+ }
+ return child_scope_t::lookup(kind, name);
+}
+
+} // namespace ledger
diff --git a/src/scope.h b/src/scope.h
new file mode 100644
index 00000000..93f80230
--- /dev/null
+++ b/src/scope.h
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup expr
+ */
+
+/**
+ * @file scope.h
+ * @author John Wiegley
+ *
+ * @ingroup expr
+ */
+#ifndef _SCOPE_H
+#define _SCOPE_H
+
+#include "op.h"
+
+namespace ledger {
+
+struct symbol_t
+{
+ enum kind_t {
+ UNKNOWN,
+ FUNCTION,
+ OPTION,
+ PRECOMMAND,
+ COMMAND,
+ DIRECTIVE,
+ FORMAT
+ };
+
+ kind_t kind;
+ string name;
+ expr_t::ptr_op_t definition;
+
+ symbol_t() : kind(UNKNOWN), name(""), definition(NULL) {
+ TRACE_CTOR(symbol_t, "");
+ }
+ symbol_t(kind_t _kind, string _name, expr_t::ptr_op_t _definition = NULL)
+ : kind(_kind), name(_name), definition(_definition) {
+ TRACE_CTOR(symbol_t, "symbol_t::kind_t, string");
+ }
+ symbol_t(const symbol_t& sym)
+ : kind(sym.kind), name(sym.name),
+ definition(sym.definition) {
+ TRACE_CTOR(symbol_t, "copy");
+ }
+ ~symbol_t() throw() {
+ TRACE_DTOR(symbol_t);
+ }
+
+ bool operator<(const symbol_t& sym) const {
+ return kind < sym.kind || name < sym.name;
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & kind;
+ ar & name;
+ ar & definition;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class scope_t
+{
+public:
+ static scope_t * default_scope;
+
+ explicit scope_t() {
+ TRACE_CTOR(scope_t, "");
+ }
+ virtual ~scope_t() {
+ TRACE_DTOR(scope_t);
+ }
+
+ virtual void define(const symbol_t::kind_t, const string&,
+ expr_t::ptr_op_t) {}
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name) = 0;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive&, const unsigned int /* version */) {}
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class child_scope_t : public noncopyable, public scope_t
+{
+public:
+ scope_t * parent;
+
+ explicit child_scope_t() : parent(NULL) {
+ TRACE_CTOR(child_scope_t, "");
+ }
+ explicit child_scope_t(scope_t& _parent)
+ : parent(&_parent) {
+ TRACE_CTOR(child_scope_t, "scope_t&");
+ }
+ virtual ~child_scope_t() {
+ TRACE_DTOR(child_scope_t);
+ }
+
+ virtual void define(const symbol_t::kind_t kind,
+ const string& name, expr_t::ptr_op_t def) {
+ if (parent)
+ parent->define(kind, name, def);
+ }
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name) {
+ if (parent)
+ return parent->lookup(kind, name);
+ return NULL;
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<scope_t>(*this);
+ ar & parent;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class symbol_scope_t : public child_scope_t
+{
+ typedef std::map<symbol_t, expr_t::ptr_op_t> symbol_map;
+
+ optional<symbol_map> symbols;
+
+public:
+ explicit symbol_scope_t() {
+ TRACE_CTOR(symbol_scope_t, "");
+ }
+ explicit symbol_scope_t(scope_t& _parent) : child_scope_t(_parent) {
+ TRACE_CTOR(symbol_scope_t, "scope_t&");
+ }
+ virtual ~symbol_scope_t() {
+ TRACE_DTOR(symbol_scope_t);
+ }
+
+ virtual void define(const symbol_t::kind_t kind, const string& name,
+ expr_t::ptr_op_t def);
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<child_scope_t>(*this);
+ ar & symbols;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class call_scope_t : public child_scope_t
+{
+ value_t args;
+
+public:
+ explicit call_scope_t(scope_t& _parent) : child_scope_t(_parent) {
+ TRACE_CTOR(call_scope_t, "scope_t&");
+ }
+ virtual ~call_scope_t() {
+ TRACE_DTOR(call_scope_t);
+ }
+
+ void set_args(const value_t& _args) {
+ args = _args;
+ }
+ value_t& value() {
+ return args;
+ }
+
+ value_t& operator[](const std::size_t index) {
+ return args[index];
+ }
+ const value_t& operator[](const std::size_t index) const {
+ return args[index];
+ }
+
+ void push_front(const value_t& val) {
+ args.push_front(val);
+ }
+ void push_back(const value_t& val) {
+ args.push_back(val);
+ }
+ void pop_back() {
+ args.pop_back();
+ }
+
+ value_t::sequence_t::const_iterator begin() const {
+ return args.begin();
+ }
+ value_t::sequence_t::const_iterator end() const {
+ return args.end();
+ }
+
+ std::size_t size() const {
+ return args.size();
+ }
+ bool empty() const {
+ return args.size() == 0;
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ explicit call_scope_t() {
+ TRACE_CTOR(call_scope_t, "");
+ }
+
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<child_scope_t>(*this);
+ ar & args;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class bind_scope_t : public child_scope_t
+{
+ bind_scope_t();
+
+public:
+ scope_t& grandchild;
+
+ explicit bind_scope_t(scope_t& _parent,
+ scope_t& _grandchild)
+ : child_scope_t(_parent), grandchild(_grandchild) {
+ TRACE_CTOR(bind_scope_t, "scope_t&, scope_t&");
+ }
+ virtual ~bind_scope_t() {
+ TRACE_DTOR(bind_scope_t);
+ }
+
+ virtual void define(const symbol_t::kind_t kind, const string& name,
+ expr_t::ptr_op_t def) {
+ parent->define(kind, name, def);
+ grandchild.define(kind, name, def);
+ }
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name) {
+ if (expr_t::ptr_op_t def = grandchild.lookup(kind, name))
+ return def;
+ return child_scope_t::lookup(kind, name);
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<child_scope_t>(*this);
+ ar & grandchild;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+template <typename T>
+T * search_scope(scope_t * ptr)
+{
+ if (T * sought = dynamic_cast<T *>(ptr))
+ return sought;
+
+ if (bind_scope_t * scope = dynamic_cast<bind_scope_t *>(ptr)) {
+ if (T * sought = search_scope<T>(&scope->grandchild))
+ return sought;
+ return search_scope<T>(scope->parent);
+ }
+ else if (child_scope_t * scope = dynamic_cast<child_scope_t *>(ptr)) {
+ return search_scope<T>(scope->parent);
+ }
+ return NULL;
+}
+
+template <typename T>
+inline T& find_scope(child_scope_t& scope, bool skip_this = true)
+{
+ if (T * sought = search_scope<T>(skip_this ? scope.parent : &scope))
+ return *sought;
+
+ throw_(std::runtime_error, _("Could not find scope"));
+ return reinterpret_cast<T&>(scope); // never executed
+}
+
+} // namespace ledger
+
+#endif // _SCOPE_H
diff --git a/src/session.cc b/src/session.cc
new file mode 100644
index 00000000..1882e554
--- /dev/null
+++ b/src/session.cc
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "session.h"
+#include "xact.h"
+#include "account.h"
+#include "journal.h"
+#include "iterators.h"
+#include "filters.h"
+#include "archive.h"
+
+namespace ledger {
+
+void set_session_context(session_t * session)
+{
+ if (session) {
+ times_initialize();
+ amount_t::initialize();
+
+ amount_t::parse_conversion("1.0m", "60s");
+ amount_t::parse_conversion("1.0h", "60m");
+
+ value_t::initialize();
+ }
+ else if (! session) {
+ value_t::shutdown();
+ amount_t::shutdown();
+ times_shutdown();
+ }
+}
+
+session_t::session_t()
+ : flush_on_next_data_file(false),
+ current_year(CURRENT_DATE().year()),
+ journal(new journal_t)
+{
+ TRACE_CTOR(session_t, "");
+
+ if (const char * home_var = std::getenv("HOME"))
+ HANDLER(price_db_).on(none, (path(home_var) / ".pricedb").string());
+ else
+ HANDLER(price_db_).on(none, path("./.pricedb").string());
+}
+
+std::size_t session_t::read_data(const string& master_account)
+{
+ bool populated_data_files = false;
+
+ if (HANDLER(file_).data_files.empty()) {
+ path file;
+ if (const char * home_var = std::getenv("HOME"))
+ file = path(home_var) / ".ledger";
+
+ if (! file.empty() && exists(file))
+ HANDLER(file_).data_files.push_back(file);
+ else
+ throw_(parse_error, "No journal file was specified (please use -f)");
+
+ populated_data_files = true;
+ }
+
+ std::size_t xact_count = 0;
+
+ account_t * acct = journal->master;
+ if (! master_account.empty())
+ acct = journal->find_account(master_account);
+
+ optional<path> price_db_path;
+ if (HANDLED(price_db_))
+ price_db_path = resolve_path(HANDLER(price_db_).str());
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+ optional<archive_t> cache;
+ if (HANDLED(cache_) && master_account.empty())
+ cache = archive_t(HANDLED(cache_).str());
+
+ if (! (cache &&
+ cache->should_load(HANDLER(file_).data_files) &&
+ cache->load(*journal.get()))) {
+#endif // HAVE_BOOST_SERIALIZATION
+ if (price_db_path) {
+ if (exists(*price_db_path)) {
+ if (journal->read(*price_db_path) > 0)
+ throw_(parse_error, _("Transactions not allowed in price history file"));
+ }
+ }
+
+ foreach (const path& pathname, HANDLER(file_).data_files) {
+ if (pathname == "-") {
+ // To avoid problems with stdin and pipes, etc., we read the entire
+ // file in beforehand into a memory buffer, and then parcel it out
+ // from there.
+ std::ostringstream buffer;
+
+ while (std::cin.good() && ! std::cin.eof()) {
+ char line[8192];
+ std::cin.read(line, 8192);
+ std::streamsize count = std::cin.gcount();
+ buffer.write(line, count);
+ }
+ buffer.flush();
+
+ std::istringstream buf_in(buffer.str());
+
+ xact_count += journal->read(buf_in, "/dev/stdin", acct);
+ journal->sources.push_back(journal_t::fileinfo_t());
+ } else {
+ xact_count += journal->read(pathname, acct);
+ }
+ }
+
+ assert(xact_count == journal->xacts.size());
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+ if (cache && cache->should_save(*journal.get()))
+ cache->save(*journal.get());
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+
+ if (populated_data_files)
+ HANDLER(file_).data_files.clear();
+
+ VERIFY(journal->valid());
+
+ return journal->xacts.size();
+}
+
+void session_t::read_journal_files()
+{
+ INFO_START(journal, "Read journal file");
+
+ string master_account;
+ if (HANDLED(master_account_))
+ master_account = HANDLER(master_account_).str();
+
+ std::size_t count = read_data(master_account);
+ if (count == 0)
+ throw_(parse_error,
+ _("Failed to locate any transactions; did you specify a valid file with -f?"));
+
+ INFO_FINISH(journal);
+
+ INFO("Found " << count << " transactions");
+}
+
+void session_t::close_journal_files()
+{
+ journal.reset();
+ amount_t::shutdown();
+
+ journal.reset(new journal_t);
+ amount_t::initialize();
+}
+
+option_t<session_t> * session_t::lookup_option(const char * p)
+{
+ switch (*p) {
+ case 'Q':
+ OPT_CH(download); // -Q
+ break;
+ case 'Z':
+ OPT_CH(price_exp_);
+ break;
+ case 'c':
+ OPT(cache_);
+ break;
+ case 'd':
+ OPT(download); // -Q
+ break;
+ case 'e':
+ OPT(european);
+ break;
+ case 'f':
+ OPT_(file_); // -f
+ break;
+ case 'i':
+ OPT(input_date_format_);
+ break;
+ case 'l':
+ OPT_ALT(price_exp_, leeway_);
+ break;
+ case 'm':
+ OPT(master_account_);
+ break;
+ case 'p':
+ OPT(price_db_);
+ else OPT(price_exp_);
+ break;
+ case 's':
+ OPT(strict);
+ break;
+ }
+ return NULL;
+}
+
+expr_t::ptr_op_t session_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
+{
+ switch (kind) {
+ case symbol_t::FUNCTION:
+ // Check if they are trying to access an option's setting or value.
+ if (option_t<session_t> * handler = lookup_option(name.c_str()))
+ return MAKE_OPT_FUNCTOR(session_t, handler);
+ break;
+
+ case symbol_t::OPTION:
+ if (option_t<session_t> * handler = lookup_option(name.c_str()))
+ return MAKE_OPT_HANDLER(session_t, handler);
+ break;
+
+ default:
+ break;
+ }
+
+ return symbol_scope_t::lookup(kind, name);
+}
+
+} // namespace ledger
diff --git a/src/session.h b/src/session.h
new file mode 100644
index 00000000..5c4612a0
--- /dev/null
+++ b/src/session.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @defgroup report Reporting
+ */
+
+/**
+ * @file session.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _SESSION_H
+#define _SESSION_H
+
+#include "interactive.h"
+#include "account.h"
+#include "journal.h"
+#include "option.h"
+#include "commodity.h"
+
+namespace ledger {
+
+class commodity_pool_t;
+class xact_t;
+
+class session_t : public symbol_scope_t
+{
+ friend void set_session_context(session_t * session);
+
+public:
+ bool flush_on_next_data_file;
+ date_t::year_type current_year;
+ std::auto_ptr<journal_t> journal;
+
+ explicit session_t();
+ virtual ~session_t() {
+ TRACE_DTOR(session_t);
+ }
+
+ void set_flush_on_next_data_file(const bool truth) {
+ flush_on_next_data_file = truth;
+ }
+
+ std::size_t read_data(const string& master_account = "");
+
+ void read_journal_files();
+ void close_journal_files();
+
+ void report_options(std::ostream& out)
+ {
+ HANDLER(cache_).report(out);
+ HANDLER(download).report(out);
+ HANDLER(european).report(out);
+ HANDLER(file_).report(out);
+ HANDLER(input_date_format_).report(out);
+ HANDLER(master_account_).report(out);
+ HANDLER(price_db_).report(out);
+ HANDLER(price_exp_).report(out);
+ HANDLER(strict).report(out);
+ }
+
+ option_t<session_t> * lookup_option(const char * p);
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
+
+ /**
+ * Option handlers
+ */
+
+ OPTION(session_t, cache_);
+ OPTION(session_t, download); // -Q
+
+ OPTION_(session_t, european, DO() {
+ commodity_t::european_by_default = true;
+ });
+
+ OPTION__
+ (session_t, price_exp_, // -Z
+ CTOR(session_t, price_exp_) { value = 24L * 3600L; }
+ DO_(args) {
+ value = args[1].to_long() * 60L;
+ });
+
+ OPTION__
+ (session_t, file_, // -f
+ std::list<path> data_files;
+ CTOR(session_t, file_) {}
+ DO_(args) {
+ assert(args.size() == 2);
+ if (parent->flush_on_next_data_file) {
+ data_files.clear();
+ parent->flush_on_next_data_file = false;
+ }
+ data_files.push_back(args[1].as_string());
+ });
+
+ OPTION_(session_t, input_date_format_, DO_(args) {
+ // This changes static variables inside times.h, which affects the basic
+ // date parser.
+ set_input_date_format(args[1].as_string().c_str());
+ });
+
+ OPTION(session_t, master_account_);
+ OPTION(session_t, price_db_);
+ OPTION(session_t, strict);
+};
+
+/**
+ * Set the current session context, transferring all static globals to point
+ * at the data structures related to this session. Although Ledger itself is
+ * not thread-safe, by locking, switching session context, then unlocking
+ * after an operation is done, multiple threads can sequentially make use of
+ * the library. Thus, a session_t maintains all of the information relating
+ * to a single usage of the Ledger library.
+ */
+void set_session_context(session_t * session);
+
+} // namespace ledger
+
+#endif // _SESSION_H
diff --git a/src/stats.cc b/src/stats.cc
new file mode 100644
index 00000000..b89a5949
--- /dev/null
+++ b/src/stats.cc
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "draft.h"
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "report.h"
+#include "session.h"
+
+namespace ledger {
+
+value_t report_statistics(call_scope_t& args)
+{
+ report_t& report(find_scope<report_t>(args));
+ std::ostream& out(report.output_stream);
+
+ const account_t::xdata_t::details_t&
+ statistics(report.session.journal->master->family_details(true));
+
+ if (! is_valid(statistics.earliest_post) &&
+ ! is_valid(statistics.latest_post))
+ return NULL_VALUE;
+
+ assert(is_valid(statistics.earliest_post));
+ assert(is_valid(statistics.latest_post));
+
+ {
+ straccstream accum;
+ out << ACCUM(accum << _("Time period: %1 to %2 (%3 days)")
+ << format_date(statistics.earliest_post)
+ << format_date(statistics.latest_post)
+ << (statistics.latest_post -
+ statistics.earliest_post).days())
+ << std::endl << std::endl;
+ }
+
+ out << _(" Files these postings came from:") << std::endl;
+
+ foreach (const path& pathname, statistics.filenames)
+ if (! pathname.empty())
+ out << " " << pathname.string() << std::endl;
+ out << std::endl;
+
+ out << _(" Unique payees: ");
+ out.width(6);
+ out << statistics.payees_referenced.size() << std::endl;
+
+ out << _(" Unique accounts: ");
+ out.width(6);
+ out << statistics.accounts_referenced.size() << std::endl;
+
+ out << std::endl;
+
+ out << _(" Number of postings: ");
+ out.width(6);
+ out << statistics.posts_count;
+
+ out << " (";
+ out.precision(2);
+ out << (double((statistics.latest_post - statistics.earliest_post).days()) /
+ double(statistics.posts_count)) << _(" per day)") << std::endl;
+
+ out << _(" Uncleared postings: ");
+ out.width(6);
+ out << (statistics.posts_count -
+ statistics.posts_cleared_count) << std::endl;
+
+ out << std::endl;
+
+ out << _(" Days since last post: ");
+ out.width(6);
+ out << (CURRENT_DATE() - statistics.latest_post).days()
+ << std::endl;
+
+ out << _(" Posts in last 7 days: ");
+ out.width(6);
+ out << statistics.posts_last_7_count << std::endl;
+ out << _(" Posts in last 30 days: ");
+ out.width(6);
+ out << statistics.posts_last_30_count << std::endl;
+ out << _(" Posts seen this month: ");
+ out.width(6);
+ out << statistics.posts_this_month_count << std::endl;
+
+ out.flush();
+
+ return NULL_VALUE;
+}
+
+} // namespace ledger
diff --git a/src/stats.h b/src/stats.h
new file mode 100644
index 00000000..d2d10de6
--- /dev/null
+++ b/src/stats.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup stats
+ */
+
+/**
+ * @file stats.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _STATS_H
+#define _STATS_H
+
+#include "value.h"
+
+namespace ledger {
+
+class call_scope_t;
+
+value_t report_statistics(call_scope_t& scope);
+
+} // namespace ledger
+
+#endif // _STATS_H
diff --git a/src/stream.cc b/src/stream.cc
new file mode 100644
index 00000000..e39b74e0
--- /dev/null
+++ b/src/stream.cc
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "stream.h"
+
+namespace ledger {
+
+namespace {
+ /**
+ * @brief Forks a child process so that Ledger may handle running a
+ * pager
+ *
+ * In order for the pager option to work, Ledger has to run the pager
+ * itself, which requires Ledger to fork a new process in order to run
+ * the pager. This function does the necessary fork. After the fork,
+ * two processes exist. One of them is exec'd to create the pager;
+ * the other is still Ledger.
+ *
+ * This function returns only for the process that is still Ledger.
+ *
+ * @param out Pointer to a pointer to the output stream. This The
+ * pointer to the output stream is changed so that the stream is
+ * connected to the stdin of the pager. The caller is responsible for
+ * cleaning this up.
+ *
+ * @param pager_path Path to the pager command.
+ *
+ * @return The file descriptor of the pipe to the pager. The caller
+ * is responsible for cleaning this up.
+ *
+ * @exception std::logic_error Some problem was encountered, such as
+ * failure to create a pipe or failure to fork a child process.
+ */
+ int do_fork(std::ostream ** os, const path& pager_path)
+ {
+ int pfd[2];
+
+ int status = pipe(pfd);
+ if (status == -1)
+ throw std::logic_error(_("Failed to create pipe"));
+
+ status = fork();
+ if (status < 0) {
+ throw std::logic_error(_("Failed to fork child process"));
+ }
+ else if (status == 0) { // child
+ // Duplicate pipe's reading end into stdin
+ status = dup2(pfd[0], STDIN_FILENO);
+ if (status == -1)
+ perror("dup2");
+
+ // Close unuseful file descriptors: the pipe's writing and reading
+ // ends (the latter is not needed anymore, after the duplication).
+ close(pfd[1]);
+ close(pfd[0]);
+
+ // Find command name: its the substring starting right of the
+ // rightmost '/' character in the pager pathname. See manpage for
+ // strrchr.
+#if BOOST_VERSION >= 103700
+ path basename(pager_path.filename());
+#else
+ path basename(pager_path.leaf());
+#endif
+ execlp(pager_path.string().c_str(), basename.string().c_str(), NULL);
+
+ // We should never, ever reach here
+ perror((std::string("execlp: ") + pager_path.string()).c_str());
+ exit(1);
+ }
+ else { // parent
+ close(pfd[0]);
+ typedef iostreams::stream<iostreams::file_descriptor_sink> fdstream;
+ *os = new fdstream(pfd[1]);
+ }
+ return pfd[1];
+ }
+}
+
+void output_stream_t::initialize(const optional<path>& output_file,
+ const optional<path>& pager_path)
+{
+ if (output_file && *output_file != "-")
+ os = new ofstream(*output_file);
+ else if (pager_path)
+ pipe_to_pager_fd = do_fork(&os, *pager_path);
+ else
+ os = &std::cout;
+}
+
+void output_stream_t::close()
+{
+ if (os != &std::cout) {
+ checked_delete(os);
+ os = &std::cout;
+ }
+
+ if (pipe_to_pager_fd != -1) {
+ ::close(pipe_to_pager_fd);
+ pipe_to_pager_fd = -1;
+
+ int status;
+ wait(&status);
+ if (! WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ throw std::logic_error(_("Error in the pager"));
+ }
+}
+
+} // namespace ledger
diff --git a/src/stream.h b/src/stream.h
new file mode 100644
index 00000000..e87da67a
--- /dev/null
+++ b/src/stream.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup util
+ */
+
+/**
+ * @file stream.h
+ * @author John Wiegley, Omari Norman
+ *
+ * @ingroup util
+ *
+ * @brief A utility class for abstracting an output stream.
+ *
+ * Because Ledger might send output to a file, the console, or a pager
+ * child process, different cleanup is needed for each scenario. This
+ * file abstracts those various needs.
+ */
+#ifndef _STREAM_H
+#define _STREAM_H
+
+#include "utils.h"
+
+namespace ledger {
+
+/**
+ * @brief An output stream
+ *
+ * A stream to output in Ledger may be going to one of three places:
+ * to stdout, to a file, or to a pager. Construct an output_stream_t and
+ * the stream will automatically be cleaned up upon destruction.
+ *
+ * This class suffers from "else-if-heimer's disease," see Marshall
+ * Cline's "C++ FAQ Lite". Arguably this should be three different
+ * classes, but that introduces additional unneeded complications.
+ */
+class output_stream_t
+{
+ output_stream_t& operator=(const output_stream_t&);
+
+private:
+ int pipe_to_pager_fd;
+
+public:
+ /**
+ * A pointer to the ostream. Don't delete this; the output_stream_t
+ * class takes care of this.
+ */
+ std::ostream * os;
+
+ /**
+ * Construct a new output_stream_t.
+ */
+ output_stream_t() : pipe_to_pager_fd(-1), os(&std::cout) {
+ TRACE_CTOR(output_stream_t, "");
+ }
+
+ /**
+ * When copy-constructed, make the copy just be a new output stream. This
+ * allows large classes to rely on their default copy-constructor without
+ * worrying about pointer copying within output_stream_t.
+ */
+ output_stream_t(const output_stream_t&)
+ : pipe_to_pager_fd(-1), os(&std::cout) {
+ TRACE_CTOR(output_stream_t, "copy");
+ }
+
+ /**
+ * Destroys an output_stream_t. This deletes the dynamically
+ * allocated ostream, if necessary. It also closes output file
+ * descriptor, if necessary.
+ */
+ ~output_stream_t() {
+ TRACE_DTOR(output_stream_t);
+ close();
+ }
+
+ /**
+ * Initialize the output stream object.
+ *
+ * @param output_file File to which to send output. If both this
+ * and pager are set, output_file takes priority.
+ *
+ * @param pager_path Path to a pager. To not use a pager, leave this
+ * empty.
+ */
+ void initialize(const optional<path>& output_file = none,
+ const optional<path>& pager_path = none);
+
+ /**
+ * Convertor to a standard ostream. This is used so that we can
+ * stream directly to an object of type output_stream_t.
+ */
+ operator std::ostream&() {
+ return *os;
+ }
+
+ /**
+ * Flushing function. A simple proxy for ostream's flush.
+ */
+ void flush() {
+ os->flush();
+ }
+
+ /**
+ * Close the output stream, waiting on the pager process if necessary.
+ */
+ void close();
+};
+
+} // namespace ledger
+
+#endif // _STREAM_H
diff --git a/src/system.hh.in b/src/system.hh.in
new file mode 100644
index 00000000..341ce129
--- /dev/null
+++ b/src/system.hh.in
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup util
+ *
+ * @file system.hh
+ * @author John Wiegley
+ *
+ * @brief All system headers needed by Ledger.
+ *
+ * These are collected here so that a pre-compiled header can be made.
+ * None of these header files (with the exception of acconf.h, when
+ * configure is re-run) are expected to change.
+ */
+#ifndef _SYSTEM_HH
+#define _SYSTEM_HH
+
+#include "config.h"
+
+#if defined(__GNUG__) && __GNUG__ < 3
+#define _XOPEN_SOURCE
+#endif
+
+#include <algorithm>
+#include <exception>
+#include <typeinfo>
+#include <locale>
+#include <stdexcept>
+#include <iostream>
+#include <streambuf>
+#include <iomanip>
+#include <fstream>
+#include <sstream>
+#include <iterator>
+#include <list>
+#include <map>
+#include <memory>
+#include <new>
+#include <set>
+#include <stack>
+#include <string>
+#include <vector>
+
+#if defined(__GNUG__) && __GNUG__ < 3
+
+namespace std {
+ inline ostream & right (ostream & i) {
+ i.setf(i.right, i.adjustfield);
+ return i;
+ }
+ inline ostream & left (ostream & i) {
+ i.setf(i.left, i.adjustfield);
+ return i;
+ }
+}
+
+typedef std::streamoff istream_pos_type;
+typedef std::streamoff ostream_pos_type;
+
+#else // ! (defined(__GNUG__) && __GNUG__ < 3)
+
+typedef std::istream::pos_type istream_pos_type;
+typedef std::ostream::pos_type ostream_pos_type;
+
+#endif
+
+#include <cassert>
+#include <cctype>
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <csignal>
+
+#if defined __FreeBSD__ && __FreeBSD__ <= 4
+// FreeBSD has a broken isspace macro, so don't use it
+#undef isspace(c)
+#endif
+
+#include <sys/stat.h>
+#if defined(WIN32)
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#if defined(HAVE_GETPWUID) || defined(HAVE_GETPWNAM)
+#include <pwd.h>
+#endif
+
+#if defined(HAVE_UNIX_PIPES)
+#include <sys/types.h>
+#include <sys/wait.h>
+#endif
+#if defined(HAVE_GETTEXT)
+#include "gettext.h"
+#define _(str) gettext(str)
+#else
+#define _(str) str
+#endif
+
+#include <gmp.h>
+#include <mpfr.h>
+#include "sha1.h"
+#include "utf8.h"
+
+#if defined(HAVE_LIBEDIT)
+#include <editline/readline.h>
+#endif
+
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/bind.hpp>
+#include <boost/cast.hpp>
+#include <boost/current_function.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/date_time/posix_time/posix_time_io.hpp>
+#include <boost/date_time/gregorian/gregorian_io.hpp>
+#include <boost/filesystem/convenience.hpp>
+#include <boost/filesystem/exception.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/foreach.hpp>
+#include <boost/function.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/write.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/operators.hpp>
+#include <boost/optional.hpp>
+#include <boost/ptr_container/ptr_list.hpp>
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/random/uniform_int.hpp>
+#include <boost/random/uniform_real.hpp>
+#include <boost/random/variate_generator.hpp>
+#if defined(HAVE_BOOST_REGEX_UNICODE)
+#include <boost/regex/icu.hpp>
+#else
+#include <boost/regex.hpp>
+#endif // HAVE_BOOST_REGEX_UNICODE
+#include <boost/variant.hpp>
+#include <boost/version.hpp>
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/archive/binary_oarchive.hpp>
+
+#include <boost/serialization/base_object.hpp>
+#include <boost/serialization/binary_object.hpp>
+#include <boost/serialization/optional.hpp>
+#include <boost/serialization/shared_ptr.hpp>
+#include <boost/serialization/variant.hpp>
+#include <boost/serialization/utility.hpp>
+#include <boost/serialization/export.hpp>
+#include <boost/serialization/level.hpp>
+#include <boost/serialization/string.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/deque.hpp>
+#include <boost/serialization/list.hpp>
+#include <boost/serialization/map.hpp>
+
+#include <boost/date_time/posix_time/time_serialize.hpp>
+#include <boost/date_time/gregorian/greg_serialize.hpp>
+
+namespace boost {
+namespace serialization {
+
+template <class Archive>
+void serialize(Archive& ar, boost::filesystem::path& p, const unsigned int)
+{
+ std::string s;
+ if (Archive::is_saving::value)
+ s = p.string();
+
+ ar & s;
+
+ if (Archive::is_loading::value)
+ p = s;
+}
+
+template <class Archive, class T>
+void serialize(Archive& ar, boost::intrusive_ptr<T>& ptr, const unsigned int)
+{
+ if (Archive::is_saving::value) {
+ T * p = ptr.get();
+ ar & p;
+ }
+ else if (Archive::is_loading::value) {
+ T * p;
+ ar & p;
+ ptr.reset(p);
+ }
+}
+
+template <class Archive, class T>
+void serialize(Archive&, boost::function<T>&, const unsigned int)
+{
+}
+
+template <class Archive>
+void serialize(Archive& ar, istream_pos_type& pos, const unsigned int)
+{
+ ar & make_binary_object(&pos, sizeof(istream_pos_type));
+}
+
+} // namespace serialization
+} // namespace boost
+
+#endif // HAVE_BOOST_SERIALIZATION
+
+#if defined(HAVE_BOOST_PYTHON)
+
+#include <boost/python.hpp>
+
+#include <boost/python/detail/wrap_python.hpp>
+#include <datetime.h>
+#include <unicodeobject.h>
+
+#include <boost/python/module_init.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#endif // HAVE_BOOST_PYTHON
+
+#endif // _SYSTEM_HH
diff --git a/src/temps.cc b/src/temps.cc
new file mode 100644
index 00000000..fd099e9a
--- /dev/null
+++ b/src/temps.cc
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "temps.h"
+
+namespace ledger {
+
+temporaries_t::~temporaries_t()
+{
+ if (post_temps) {
+ foreach (post_t& post, *post_temps) {
+ if (! post.xact->has_flags(ITEM_TEMP))
+ post.xact->remove_post(&post);
+
+ if (post.account && ! post.account->has_flags(ACCOUNT_TEMP))
+ post.account->remove_post(&post);
+ }
+ }
+
+ if (acct_temps) {
+ foreach (account_t& acct, *acct_temps) {
+ if (acct.parent && ! acct.parent->has_flags(ACCOUNT_TEMP))
+ acct.parent->remove_account(&acct);
+ }
+ }
+}
+
+xact_t& temporaries_t::copy_xact(xact_t& origin)
+{
+ if (! xact_temps)
+ xact_temps = std::list<xact_t>();
+
+ xact_temps->push_back(origin);
+ xact_t& temp(xact_temps->back());
+
+ temp.add_flags(ITEM_TEMP);
+ return temp;
+}
+
+xact_t& temporaries_t::create_xact()
+{
+ if (! xact_temps)
+ xact_temps = std::list<xact_t>();
+
+ xact_temps->push_back(xact_t());
+ xact_t& temp(xact_temps->back());
+
+ temp.add_flags(ITEM_TEMP);
+ return temp;
+}
+
+post_t& temporaries_t::copy_post(post_t& origin, xact_t& xact,
+ account_t * account)
+{
+ if (! post_temps)
+ post_temps = std::list<post_t>();
+
+ post_temps->push_back(origin);
+ post_t& temp(post_temps->back());
+
+ if (account)
+ temp.account = account;
+ temp.add_flags(ITEM_TEMP);
+
+ temp.account->add_post(&temp);
+ xact.add_post(&temp);
+
+ return temp;
+}
+
+post_t& temporaries_t::create_post(xact_t& xact, account_t * account)
+{
+ if (! post_temps)
+ post_temps = std::list<post_t>();
+
+ post_temps->push_back(post_t(account));
+ post_t& temp(post_temps->back());
+
+ temp.account = account;
+ temp.add_flags(ITEM_TEMP);
+
+ temp.account->add_post(&temp);
+ xact.add_post(&temp);
+
+ return temp;
+}
+
+account_t& temporaries_t::create_account(const string& name,
+ account_t * parent)
+{
+ if (! acct_temps)
+ acct_temps = std::list<account_t>();
+
+ acct_temps->push_back(account_t(parent, name));
+ account_t& temp(acct_temps->back());
+
+ if (parent)
+ parent->add_account(&temp);
+
+ temp.add_flags(ACCOUNT_TEMP);
+ return temp;
+}
+
+} // namespace ledger
diff --git a/src/temps.h b/src/temps.h
new file mode 100644
index 00000000..4243079c
--- /dev/null
+++ b/src/temps.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup report
+ */
+
+/**
+ * @file temps.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ */
+#ifndef _TEMPS_H
+#define _TEMPS_H
+
+namespace ledger {
+
+class temporaries_t
+{
+ optional<std::list<xact_t> > xact_temps;
+ optional<std::list<post_t> > post_temps;
+ optional<std::list<account_t> > acct_temps;
+
+public:
+ ~temporaries_t();
+
+ xact_t& copy_xact(xact_t& origin);
+ xact_t& create_xact();
+ xact_t& last_xact() {
+ return xact_temps->back();
+ }
+ post_t& copy_post(post_t& origin, xact_t& xact,
+ account_t * account = NULL);
+ post_t& create_post(xact_t& xact, account_t * account);
+ post_t& last_post() {
+ return post_temps->back();
+ }
+ account_t& create_account(const string& name = "",
+ account_t * parent = NULL);
+ account_t& last_account() {
+ return acct_temps->back();
+ }
+};
+
+} // namespace ledger
+
+#endif // _TEMPS_H
diff --git a/src/textual.cc b/src/textual.cc
new file mode 100644
index 00000000..cf670cae
--- /dev/null
+++ b/src/textual.cc
@@ -0,0 +1,1396 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "journal.h"
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "option.h"
+#include "query.h"
+#include "pstream.h"
+#include "pool.h"
+#include "session.h"
+
+#define TIMELOG_SUPPORT 1
+#if defined(TIMELOG_SUPPORT)
+#include "timelog.h"
+#endif
+
+namespace ledger {
+
+namespace {
+ class instance_t : public noncopyable, public scope_t
+ {
+ static const std::size_t MAX_LINE = 1024;
+
+ public:
+ typedef std::pair<commodity_t *, amount_t> fixed_rate_t;
+ typedef variant<account_t *, string, fixed_rate_t> state_t;
+
+ std::list<state_t>& state_stack;
+
+#if defined(TIMELOG_SUPPORT)
+ time_log_t& timelog;
+#endif
+ instance_t * parent;
+ std::istream& in;
+ scope_t& scope;
+ journal_t& journal;
+ account_t * master;
+ const path * original_file;
+ accounts_map account_aliases;
+ bool strict;
+ path pathname;
+ char linebuf[MAX_LINE + 1];
+ std::size_t linenum;
+ istream_pos_type line_beg_pos;
+ istream_pos_type curr_pos;
+ std::size_t count;
+ std::size_t errors;
+
+ optional<date_t::year_type> current_year;
+
+ instance_t(std::list<state_t>& _state_stack,
+#if defined(TIMELOG_SUPPORT)
+ time_log_t& _timelog,
+#endif
+ std::istream& _in,
+ scope_t& _scope,
+ journal_t& _journal,
+ account_t * _master = NULL,
+ const path * _original_file = NULL,
+ bool _strict = false,
+ instance_t * _parent = NULL);
+
+ ~instance_t();
+
+ bool front_is_account() {
+ return state_stack.front().type() == typeid(account_t *);
+ }
+ bool front_is_string() {
+ return state_stack.front().type() == typeid(string);
+ }
+ bool front_is_fixed_rate() {
+ return state_stack.front().type() == typeid(fixed_rate_t);
+ }
+
+ account_t * top_account() {
+ foreach (state_t& state, state_stack)
+ if (state.type() == typeid(account_t *))
+ return boost::get<account_t *>(state);
+ return NULL;
+ }
+
+ void parse();
+ std::streamsize read_line(char *& line);
+ bool peek_whitespace_line() {
+ return (in.good() && ! in.eof() &&
+ (in.peek() == ' ' || in.peek() == '\t'));
+ }
+
+ void read_next_directive();
+
+#if defined(TIMELOG_SUPPORT)
+ void clock_in_directive(char * line, bool capitalized);
+ void clock_out_directive(char * line, bool capitalized);
+#endif
+
+ void default_commodity_directive(char * line);
+ void default_account_directive(char * line);
+ void price_conversion_directive(char * line);
+ void price_xact_directive(char * line);
+ void nomarket_directive(char * line);
+ void year_directive(char * line);
+ void option_directive(char * line);
+ void automated_xact_directive(char * line);
+ void period_xact_directive(char * line);
+ void xact_directive(char * line, std::streamsize len);
+ void include_directive(char * line);
+ void master_account_directive(char * line);
+ void end_directive(char * line);
+ void alias_directive(char * line);
+ void fixed_directive(char * line);
+ void tag_directive(char * line);
+ void define_directive(char * line);
+ bool general_directive(char * line);
+
+ post_t * parse_post(char * line,
+ std::streamsize len,
+ account_t * account,
+ xact_t * xact,
+ bool honor_strict = true,
+ bool defer_expr = false);
+
+ bool parse_posts(account_t * account,
+ xact_base_t& xact,
+ const bool defer_expr = false);
+
+ xact_t * parse_xact(char * line,
+ std::streamsize len,
+ account_t * account);
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
+ };
+
+ void parse_amount_expr(scope_t& scope,
+ std::istream& in,
+ amount_t& amount,
+ optional<expr_t> * amount_expr,
+ post_t * post,
+ const parse_flags_t& flags = PARSE_DEFAULT,
+ const bool defer_expr = false)
+ {
+ expr_t expr(in, flags.plus_flags(PARSE_PARTIAL));
+
+ DEBUG("textual.parse", "Parsed an amount expression");
+
+#if defined(DEBUG_ENABLED)
+ DEBUG_IF("textual.parse") {
+ if (_debug_stream) {
+ ledger::dump_value_expr(*_debug_stream, expr);
+ *_debug_stream << std::endl;
+ }
+ }
+#endif
+
+ if (expr) {
+ bind_scope_t bound_scope(scope, *post);
+ if (defer_expr) {
+ assert(amount_expr);
+ *amount_expr = expr;
+ (*amount_expr)->compile(bound_scope);
+ } else {
+ value_t result(expr.calc(bound_scope));
+ if (result.is_long()) {
+ amount = result.to_amount();
+ } else {
+ if (! result.is_amount())
+ throw_(amount_error,
+ _("Amount expressions must result in a simple amount"));
+ amount = result.as_amount();
+ }
+ DEBUG("textual.parse", "The posting amount is " << amount);
+ }
+ }
+ }
+}
+
+instance_t::instance_t(std::list<state_t>& _state_stack,
+#if defined(TIMELOG_SUPPORT)
+ time_log_t& _timelog,
+#endif
+ std::istream& _in,
+ scope_t& _scope,
+ journal_t& _journal,
+ account_t * _master,
+ const path * _original_file,
+ bool _strict,
+ instance_t * _parent)
+ : state_stack(_state_stack),
+#if defined(TIMELOG_SUPPORT)
+ timelog(_timelog),
+#endif
+ parent(_parent), in(_in), scope(_scope),
+ journal(_journal), master(_master),
+ original_file(_original_file), strict(_strict)
+{
+ TRACE_CTOR(instance_t, "...");
+
+ if (! master)
+ master = journal.master;
+ state_stack.push_front(master);
+
+ if (_original_file)
+ pathname = *_original_file;
+ else
+ pathname = "/dev/stdin";
+}
+
+instance_t::~instance_t()
+{
+ TRACE_DTOR(instance_t);
+
+ assert(! state_stack.empty());
+ state_stack.pop_front();
+}
+
+void instance_t::parse()
+{
+ INFO("Parsing file '" << pathname.string() << "'");
+
+ TRACE_START(instance_parse, 1,
+ "Done parsing file '" << pathname.string() << "'");
+
+ if (! in.good() || in.eof())
+ return;
+
+ linenum = 0;
+ errors = 0;
+ count = 0;
+ curr_pos = in.tellg();
+
+ while (in.good() && ! in.eof()) {
+ try {
+ read_next_directive();
+ }
+ catch (const std::exception& err) {
+ string current_context = error_context();
+
+ if (parent) {
+ std::list<instance_t *> instances;
+
+ for (instance_t * instance = parent;
+ instance;
+ instance = instance->parent)
+ instances.push_front(instance);
+
+ foreach (instance_t * instance, instances)
+ add_error_context(_("In file included from %1")
+ << file_context(instance->pathname,
+ instance->linenum));
+ }
+ add_error_context(_("While parsing file %1")
+ << file_context(pathname, linenum));
+
+ if (caught_signal != NONE_CAUGHT)
+ throw;
+
+ string context = error_context();
+ if (! context.empty())
+ std::cerr << context << std::endl;
+
+ if (! current_context.empty())
+ std::cerr << current_context << std::endl;
+
+ std::cerr << _("Error: ") << err.what() << std::endl;
+ errors++;
+ }
+ }
+
+ TRACE_STOP(instance_parse, 1);
+}
+
+std::streamsize instance_t::read_line(char *& line)
+{
+ assert(in.good());
+ assert(! in.eof()); // no one should call us in that case
+
+ line_beg_pos = curr_pos;
+
+ check_for_signal();
+
+ in.getline(linebuf, MAX_LINE);
+ std::streamsize len = in.gcount();
+
+ if (len > 0) {
+ if (linenum == 0 && utf8::is_bom(linebuf))
+ line = &linebuf[3];
+ else
+ line = linebuf;
+
+ if (line[len - 1] == '\r') // strip Windows CRLF down to LF
+ line[--len] = '\0';
+
+ linenum++;
+
+ curr_pos = line_beg_pos;
+ curr_pos += len;
+
+ return len - 1; // LF is being silently dropped
+ }
+ return 0;
+}
+
+void instance_t::read_next_directive()
+{
+ char * line;
+ std::streamsize len = read_line(line);
+
+ if (len == 0 || line == NULL)
+ return;
+
+ switch (line[0]) {
+ case '\0':
+ assert(false); // shouldn't ever reach here
+ break;
+
+ case ' ':
+ case '\t': {
+ break;
+ }
+
+ case ';': // comments
+ case '#':
+ case '*':
+ case '|':
+ break;
+
+ case '-': // option setting
+ option_directive(line);
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ xact_directive(line, len);
+ break;
+ case '=': // automated xact
+ automated_xact_directive(line);
+ break;
+ case '~': // period xact
+ period_xact_directive(line);
+ break;
+
+ case '@':
+ case '!':
+ line++;
+ // fall through...
+ default: // some other directive
+ if (! general_directive(line)) {
+ switch (line[0]) {
+#if defined(TIMELOG_SUPPORT)
+ case 'i':
+ clock_in_directive(line, false);
+ break;
+ case 'I':
+ clock_in_directive(line, true);
+ break;
+
+ case 'o':
+ clock_out_directive(line, false);
+ break;
+ case 'O':
+ clock_out_directive(line, true);
+ break;
+
+ case 'h':
+ case 'b':
+ break;
+#endif // TIMELOG_SUPPORT
+
+ case 'A': // a default account for unbalanced posts
+ default_account_directive(line);
+ break;
+ case 'C': // a set of conversions
+ price_conversion_directive(line);
+ break;
+ case 'D': // a default commodity for "xact"
+ default_commodity_directive(line);
+ break;
+ case 'N': // don't download prices
+ nomarket_directive(line);
+ break;
+ case 'P': // a pricing xact
+ price_xact_directive(line);
+ break;
+ case 'Y': // set the current year
+ year_directive(line);
+ break;
+ }
+ }
+ break;
+ }
+}
+
+#if defined(TIMELOG_SUPPORT)
+
+void instance_t::clock_in_directive(char * line,
+ bool /*capitalized*/)
+{
+ string datetime(line, 2, 19);
+
+ char * p = skip_ws(line + 22);
+ char * n = next_element(p, true);
+ char * end = n ? next_element(n, true) : NULL;
+
+ if (end && *end == ';')
+ end = skip_ws(end + 1);
+ else
+ end = NULL;
+
+ position_t position;
+ position.pathname = pathname;
+ position.beg_pos = line_beg_pos;
+ position.beg_line = linenum;
+ position.end_pos = curr_pos;
+ position.end_line = linenum;
+
+ time_xact_t event(position, parse_datetime(datetime, current_year),
+ p ? top_account()->find_account(p) : NULL,
+ n ? n : "",
+ end ? end : "");
+
+ timelog.clock_in(event);
+}
+
+void instance_t::clock_out_directive(char * line,
+ bool /*capitalized*/)
+{
+ string datetime(line, 2, 19);
+
+ char * p = skip_ws(line + 22);
+ char * n = next_element(p, true);
+ char * end = n ? next_element(n, true) : NULL;
+
+ if (end && *end == ';')
+ end = skip_ws(end + 1);
+ else
+ end = NULL;
+
+ position_t position;
+ position.pathname = pathname;
+ position.beg_pos = line_beg_pos;
+ position.beg_line = linenum;
+ position.end_pos = curr_pos;
+ position.end_line = linenum;
+
+ time_xact_t event(position, parse_datetime(datetime, current_year),
+ p ? top_account()->find_account(p) : NULL,
+ n ? n : "",
+ end ? end : "");
+
+ timelog.clock_out(event);
+ count++;
+}
+
+#endif // TIMELOG_SUPPORT
+
+void instance_t::default_commodity_directive(char * line)
+{
+ amount_t amt(skip_ws(line + 1));
+ VERIFY(amt.valid());
+ commodity_pool_t::current_pool->default_commodity = &amt.commodity();
+ amt.commodity().add_flags(COMMODITY_KNOWN);
+}
+
+void instance_t::default_account_directive(char * line)
+{
+ journal.bucket = top_account()->find_account(skip_ws(line + 1));
+ journal.bucket->add_flags(ACCOUNT_KNOWN);
+}
+
+void instance_t::price_conversion_directive(char * line)
+{
+ if (char * p = std::strchr(line + 1, '=')) {
+ *p++ = '\0';
+ amount_t::parse_conversion(line + 1, p);
+ }
+}
+
+void instance_t::price_xact_directive(char * line)
+{
+ optional<std::pair<commodity_t *, price_point_t> > point =
+ commodity_pool_t::current_pool->parse_price_directive(skip_ws(line + 1));
+ if (! point)
+ throw parse_error(_("Pricing entry failed to parse"));
+}
+
+void instance_t::nomarket_directive(char * line)
+{
+ char * p = skip_ws(line + 1);
+ string symbol;
+ commodity_t::parse_symbol(p, symbol);
+
+ if (commodity_t * commodity =
+ commodity_pool_t::current_pool->find_or_create(symbol))
+ commodity->add_flags(COMMODITY_NOMARKET | COMMODITY_KNOWN);
+}
+
+void instance_t::year_directive(char * line)
+{
+ current_year = lexical_cast<unsigned short>(skip_ws(line + 1));
+}
+
+void instance_t::option_directive(char * line)
+{
+ char * p = next_element(line);
+ if (! p) {
+ p = std::strchr(line, '=');
+ if (p)
+ *p++ = '\0';
+ }
+
+ if (! process_option(pathname.string(), line + 2, scope, p, line))
+ throw_(option_error, _("Illegal option --%1") << line + 2);
+}
+
+void instance_t::automated_xact_directive(char * line)
+{
+ istream_pos_type pos = line_beg_pos;
+ std::size_t lnum = linenum;
+
+ bool reveal_context = true;
+
+ try {
+
+ std::auto_ptr<auto_xact_t> ae
+ (new auto_xact_t(query_t(string(skip_ws(line + 1)),
+ keep_details_t(true, true, true))));
+
+ reveal_context = false;
+
+ if (parse_posts(top_account(), *ae.get(), true)) {
+ reveal_context = true;
+
+ journal.auto_xacts.push_back(ae.get());
+
+ ae->journal = &journal;
+ ae->pos = position_t();
+ ae->pos->pathname = pathname;
+ ae->pos->beg_pos = pos;
+ ae->pos->beg_line = lnum;
+ ae->pos->end_pos = curr_pos;
+ ae->pos->end_line = linenum;
+
+ ae.release();
+ }
+
+ }
+ catch (const std::exception& err) {
+ if (reveal_context) {
+ add_error_context(_("While parsing periodic transaction:"));
+ add_error_context(source_context(pathname, pos, curr_pos, "> "));
+ }
+ throw;
+ }
+}
+
+void instance_t::period_xact_directive(char * line)
+{
+ istream_pos_type pos = line_beg_pos;
+ std::size_t lnum = linenum;
+
+ bool reveal_context = true;
+
+ try {
+
+ std::auto_ptr<period_xact_t> pe(new period_xact_t(skip_ws(line + 1)));
+
+ reveal_context = false;
+
+ if (parse_posts(top_account(), *pe.get())) {
+ reveal_context = true;
+ pe->journal = &journal;
+
+ if (pe->finalize()) {
+ journal.extend_xact(pe.get());
+ journal.period_xacts.push_back(pe.get());
+
+ pe->pos = position_t();
+ pe->pos->pathname = pathname;
+ pe->pos->beg_pos = pos;
+ pe->pos->beg_line = lnum;
+ pe->pos->end_pos = curr_pos;
+ pe->pos->end_line = linenum;
+
+ pe.release();
+ } else {
+ pe->journal = NULL;
+ throw parse_error(_("Period transaction failed to balance"));
+ }
+ }
+
+ }
+ catch (const std::exception& err) {
+ if (reveal_context) {
+ add_error_context(_("While parsing periodic transaction:"));
+ add_error_context(source_context(pathname, pos, curr_pos, "> "));
+ }
+ throw;
+ }
+}
+
+void instance_t::xact_directive(char * line, std::streamsize len)
+{
+ TRACE_START(xacts, 1, "Time spent handling transactions:");
+
+ if (xact_t * xact = parse_xact(line, len, top_account())) {
+ std::auto_ptr<xact_t> manager(xact);
+
+ if (journal.add_xact(xact)) {
+ manager.release(); // it's owned by the journal now
+ count++;
+ }
+ // It's perfectly valid for the journal to reject the xact, which it will
+ // do if the xact has no substantive effect (for example, a checking
+ // xact, all of whose postings have null amounts).
+ } else {
+ throw parse_error(_("Failed to parse transaction"));
+ }
+
+ TRACE_STOP(xacts, 1);
+}
+
+void instance_t::include_directive(char * line)
+{
+ path filename;
+
+ if (line[0] != '/' && line[0] != '\\' && line[0] != '~') {
+ string::size_type pos = pathname.string().rfind('/');
+ if (pos == string::npos)
+ pos = pathname.string().rfind('\\');
+ if (pos != string::npos)
+ filename = path(string(pathname.string(), 0, pos + 1)) / line;
+ } else {
+ filename = line;
+ }
+
+ filename = resolve_path(filename);
+
+ DEBUG("textual.include", "Line " << linenum << ": " <<
+ "Including path '" << filename << "'");
+
+ if (! exists(filename))
+ throw_(std::runtime_error,
+ _("File to include was not found: '%1'") << filename);
+
+ ifstream stream(filename);
+
+ instance_t instance(state_stack,
+#if defined(TIMELOG_SUPPORT)
+ timelog,
+#endif
+ stream, scope, journal, master,
+ &filename, strict, this);
+ instance.parse();
+
+ errors += instance.errors;
+ count += instance.count;
+}
+
+void instance_t::master_account_directive(char * line)
+{
+ if (account_t * acct = top_account()->find_account(line))
+ state_stack.push_front(acct);
+ else
+ assert(! "Failed to create account");
+}
+
+void instance_t::end_directive(char * kind)
+{
+ string name(kind);
+
+ if ((name.empty() || name == "account") && ! front_is_account())
+ throw_(std::runtime_error,
+ _("'end account' directive does not match open directive"));
+ else if (name == "tag" && ! front_is_string())
+ throw_(std::runtime_error,
+ _("'end tag' directive does not match open directive"));
+ else if (name == "fixed" && ! front_is_fixed_rate())
+ throw_(std::runtime_error,
+ _("'end fixed' directive does not match open directive"));
+
+ if (state_stack.size() <= 1)
+ throw_(std::runtime_error,
+ _("'end' found, but no enclosing tag or account directive"));
+ else
+ state_stack.pop_front();
+}
+
+void instance_t::alias_directive(char * line)
+{
+ char * b = skip_ws(line);
+ if (char * e = std::strchr(b, '=')) {
+ char * z = e - 1;
+ while (std::isspace(*z))
+ *z-- = '\0';
+ *e++ = '\0';
+ e = skip_ws(e);
+
+ // Once we have an alias name (b) and the target account
+ // name (e), add a reference to the account in the
+ // `account_aliases' map, which is used by the post
+ // parser to resolve alias references.
+ account_t * acct = top_account()->find_account(e);
+ std::pair<accounts_map::iterator, bool> result
+ = account_aliases.insert(accounts_map::value_type(b, acct));
+ assert(result.second);
+ }
+}
+
+void instance_t::fixed_directive(char * line)
+{
+ if (optional<std::pair<commodity_t *, price_point_t> > price_point =
+ commodity_pool_t::current_pool->parse_price_directive(trim_ws(line),
+ true)) {
+ state_stack.push_front(fixed_rate_t(price_point->first,
+ price_point->second.price));
+ } else {
+ throw_(std::runtime_error, _("Error in fixed directive"));
+ }
+}
+
+void instance_t::tag_directive(char * line)
+{
+ string tag(trim_ws(line));
+
+ if (tag.find(':') == string::npos)
+ tag = string(":") + tag + ":";
+
+ state_stack.push_front(tag);
+}
+
+void instance_t::define_directive(char * line)
+{
+ expr_t def(skip_ws(line));
+ def.compile(scope); // causes definitions to be established
+}
+
+bool instance_t::general_directive(char * line)
+{
+ char buf[8192];
+
+ std::strcpy(buf, line);
+
+ char * p = buf;
+ char * arg = next_element(buf);
+
+ if (*p == '@' || *p == '!')
+ p++;
+
+ switch (*p) {
+ case 'a':
+ if (std::strcmp(p, "account") == 0) {
+ master_account_directive(arg);
+ return true;
+ }
+ else if (std::strcmp(p, "alias") == 0) {
+ alias_directive(arg);
+ return true;
+ }
+ break;
+
+ case 'b':
+ if (std::strcmp(p, "bucket") == 0) {
+ default_account_directive(arg);
+ return true;
+ }
+ break;
+
+ case 'd':
+ if (std::strcmp(p, "def") == 0 || std::strcmp(p, "define") == 0) {
+ define_directive(arg);
+ return true;
+ }
+ break;
+
+ case 'e':
+ if (std::strcmp(p, "end") == 0) {
+ end_directive(arg);
+ return true;
+ }
+ break;
+
+ case 'f':
+ if (std::strcmp(p, "fixed") == 0) {
+ fixed_directive(arg);
+ return true;
+ }
+ break;
+
+ case 'i':
+ if (std::strcmp(p, "include") == 0) {
+ include_directive(arg);
+ return true;
+ }
+ break;
+
+ case 't':
+ if (std::strcmp(p, "tag") == 0) {
+ tag_directive(arg);
+ return true;
+ }
+ break;
+
+ case 'y':
+ if (std::strcmp(p, "year") == 0) {
+ year_directive(arg);
+ return true;
+ }
+ break;
+ }
+
+ if (expr_t::ptr_op_t op = lookup(symbol_t::DIRECTIVE, p)) {
+ call_scope_t args(*this);
+ args.push_back(string_value(p));
+ op->as_function()(args);
+ return true;
+ }
+
+ return false;
+}
+
+post_t * instance_t::parse_post(char * line,
+ std::streamsize len,
+ account_t * account,
+ xact_t * xact,
+ bool honor_strict,
+ bool defer_expr)
+{
+ TRACE_START(post_details, 1, "Time spent parsing postings:");
+
+ std::auto_ptr<post_t> post(new post_t);
+
+ post->xact = xact; // this could be NULL
+ post->pos = position_t();
+ post->pos->pathname = pathname;
+ post->pos->beg_pos = line_beg_pos;
+ post->pos->beg_line = linenum;
+
+ char buf[MAX_LINE + 1];
+ std::strcpy(buf, line);
+ std::size_t beg = 0;
+
+ try {
+
+ // Parse the state flag
+
+ assert(line);
+ assert(*line);
+
+ char * p = skip_ws(line);
+
+ switch (*p) {
+ case '*':
+ post->set_state(item_t::CLEARED);
+ p = skip_ws(p + 1);
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Parsed the CLEARED flag");
+ break;
+
+ case '!':
+ post->set_state(item_t::PENDING);
+ p = skip_ws(p + 1);
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Parsed the PENDING flag");
+ break;
+ }
+
+ if (xact &&
+ ((xact->_state == item_t::CLEARED && post->_state != item_t::CLEARED) ||
+ (xact->_state == item_t::PENDING && post->_state == item_t::UNCLEARED)))
+ post->set_state(xact->_state);
+
+ // Parse the account name
+
+ if (! *p)
+ throw parse_error(_("Posting has no account"));
+
+ char * next = next_element(p, true);
+ char * e = p + std::strlen(p);
+
+ while (e > p && std::isspace(*(e - 1)))
+ e--;
+
+ if ((*p == '[' && *(e - 1) == ']') || (*p == '(' && *(e - 1) == ')')) {
+ post->add_flags(POST_VIRTUAL);
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Parsed a virtual account name");
+
+ if (*p == '[') {
+ post->add_flags(POST_MUST_BALANCE);
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Posting must balance");
+ }
+ p++; e--;
+ }
+
+ string name(p, e - p);
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Parsed account name " << name);
+
+ if (account_aliases.size() > 0) {
+ accounts_map::const_iterator i = account_aliases.find(name);
+ if (i != account_aliases.end())
+ post->account = (*i).second;
+ }
+ if (! post->account)
+ post->account = account->find_account(name);
+
+ if (honor_strict && strict && ! post->account->has_flags(ACCOUNT_KNOWN)) {
+ if (post->_state == item_t::UNCLEARED)
+ warning_(_("\"%1\", line %2: Unknown account '%3'")
+ << pathname << linenum << post->account->fullname());
+ post->account->add_flags(ACCOUNT_KNOWN);
+ }
+
+ // Parse the optional amount
+
+ bool saw_amount = false;
+
+ if (next && *next && (*next != ';' && *next != '=')) {
+ saw_amount = true;
+
+ beg = next - line;
+ ptristream stream(next, len - beg);
+
+ if (*next != '(') // indicates a value expression
+ post->amount.parse(stream, PARSE_NO_REDUCE);
+ else
+ parse_amount_expr(scope, stream, post->amount, &post->amount_expr,
+ post.get(), PARSE_NO_REDUCE | PARSE_SINGLE |
+ PARSE_NO_ASSIGN, defer_expr);
+
+ if (! post->amount.is_null() && post->amount.has_commodity()) {
+ if (honor_strict && strict &&
+ ! post->amount.commodity().has_flags(COMMODITY_KNOWN)) {
+ if (post->_state == item_t::UNCLEARED)
+ warning_(_("\"%1\", line %2: Unknown commodity '%3'")
+ << pathname << linenum << post->amount.commodity());
+ post->amount.commodity().add_flags(COMMODITY_KNOWN);
+ }
+
+ if (! post->amount.has_annotation()) {
+ foreach (state_t& state, state_stack) {
+ if (state.type() == typeid(fixed_rate_t)) {
+ fixed_rate_t& rate(boost::get<fixed_rate_t>(state));
+ if (*rate.first == post->amount.commodity()) {
+ annotation_t details(rate.second);
+ details.add_flags(ANNOTATION_PRICE_FIXATED);
+ post->amount.annotate(details);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "post amount = " << post->amount);
+
+ if (stream.eof()) {
+ next = NULL;
+ } else {
+ next = skip_ws(next + static_cast<std::ptrdiff_t>(stream.tellg()));
+
+ // Parse the optional cost (@ PER-UNIT-COST, @@ TOTAL-COST)
+
+ if (*next == '@') {
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Found a price indicator");
+
+ bool per_unit = true;
+
+ if (*++next == '@') {
+ per_unit = false;
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "And it's for a total price");
+ }
+
+ beg = ++next - line;
+
+ p = skip_ws(next);
+ if (*p) {
+ post->cost = amount_t();
+
+ beg = p - line;
+ ptristream cstream(p, len - beg);
+
+ if (*p != '(') // indicates a value expression
+ post->cost->parse(cstream, PARSE_NO_MIGRATE);
+ else
+ parse_amount_expr(scope, cstream, *post->cost, NULL, post.get(),
+ PARSE_NO_MIGRATE | PARSE_SINGLE | PARSE_NO_ASSIGN,
+ defer_expr);
+
+ if (post->cost->sign() < 0)
+ throw parse_error(_("A posting's cost may not be negative"));
+
+ post->cost->in_place_unround();
+
+ if (per_unit) {
+ // For the sole case where the cost might be uncommoditized,
+ // guarantee that the commodity of the cost after multiplication
+ // is the same as it was before.
+ commodity_t& cost_commodity(post->cost->commodity());
+ *post->cost *= post->amount;
+ post->cost->set_commodity(cost_commodity);
+ }
+
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Total cost is " << *post->cost);
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Annotated amount is " << post->amount);
+
+ if (cstream.eof())
+ next = NULL;
+ else
+ next = skip_ws(p + static_cast<std::ptrdiff_t>(cstream.tellg()));
+ } else {
+ throw parse_error(_("Expected a cost amount"));
+ }
+ }
+ }
+ }
+
+ // Parse the optional balance assignment
+
+ if (xact && next && *next == '=') {
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Found a balance assignment indicator");
+
+ beg = ++next - line;
+
+ p = skip_ws(next);
+ if (*p) {
+ post->assigned_amount = amount_t();
+
+ beg = p - line;
+ ptristream stream(p, len - beg);
+
+ if (*p != '(') // indicates a value expression
+ post->assigned_amount->parse(stream, PARSE_NO_MIGRATE);
+ else
+ parse_amount_expr(scope, stream, *post->assigned_amount, NULL,
+ post.get(), PARSE_SINGLE | PARSE_NO_MIGRATE,
+ defer_expr);
+
+ if (post->assigned_amount->is_null()) {
+ if (post->amount.is_null())
+ throw parse_error(_("Balance assignment must evaluate to a constant"));
+ else
+ throw parse_error(_("Balance assertion must evaluate to a constant"));
+ }
+
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "POST assign: parsed amt = " << *post->assigned_amount);
+
+ amount_t& amt(*post->assigned_amount);
+ value_t account_total
+ (post->account->amount(false).strip_annotations(keep_details_t()));
+
+ DEBUG("post.assign",
+ "line " << linenum << ": " "account balance = " << account_total);
+ DEBUG("post.assign",
+ "line " << linenum << ": " "post amount = " << amt);
+
+ amount_t diff = amt;
+
+ switch (account_total.type()) {
+ case value_t::AMOUNT:
+ diff -= account_total.as_amount();
+ break;
+
+ case value_t::BALANCE:
+ if (optional<amount_t> comm_bal =
+ account_total.as_balance().commodity_amount(amt.commodity()))
+ diff -= *comm_bal;
+ break;
+
+ default:
+ break;
+ }
+
+ DEBUG("post.assign",
+ "line " << linenum << ": " << "diff = " << diff);
+ DEBUG("textual.parse",
+ "line " << linenum << ": " << "POST assign: diff = " << diff);
+
+ if (! diff.is_zero()) {
+ if (! post->amount.is_null()) {
+ diff -= post->amount;
+ if (! diff.is_zero())
+ throw_(parse_error, _("Balance assertion off by %1") << diff);
+ } else {
+ post->amount = diff;
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Overwrite null posting");
+ }
+ }
+
+ if (stream.eof())
+ next = NULL;
+ else
+ next = skip_ws(p + static_cast<std::ptrdiff_t>(stream.tellg()));
+ } else {
+ throw parse_error(_("Expected an balance assignment/assertion amount"));
+ }
+ }
+
+ // Parse the optional note
+
+ if (next && *next == ';') {
+ post->append_note(++next, current_year);
+ next = line + len;
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Parsed a posting note");
+ }
+
+ // There should be nothing more to read
+
+ if (next && *next)
+ throw_(parse_error,
+ _("Unexpected char '%1' (Note: inline math requires parentheses)")
+ << *next);
+
+ post->pos->end_pos = curr_pos;
+ post->pos->end_line = linenum;
+
+ if (! state_stack.empty()) {
+ foreach (const state_t& state, state_stack)
+ if (state.type() == typeid(string))
+ post->parse_tags(boost::get<string>(state).c_str());
+ }
+
+ TRACE_STOP(post_details, 1);
+
+ return post.release();
+
+ }
+ catch (const std::exception& err) {
+ add_error_context(_("While parsing posting:"));
+ add_error_context(line_context(buf, beg, len));
+ throw;
+ }
+}
+
+bool instance_t::parse_posts(account_t * account,
+ xact_base_t& xact,
+ const bool defer_expr)
+{
+ TRACE_START(xact_posts, 1, "Time spent parsing postings:");
+
+ bool added = false;
+
+ while (peek_whitespace_line()) {
+ char * line;
+ std::streamsize len = read_line(line);
+ assert(len > 0);
+
+ if (post_t * post =
+ parse_post(line, len, account, NULL, /* honor_strict= */ false,
+ defer_expr)) {
+ xact.add_post(post);
+ added = true;
+ }
+ }
+
+ TRACE_STOP(xact_posts, 1);
+
+ return added;
+}
+
+xact_t * instance_t::parse_xact(char * line,
+ std::streamsize len,
+ account_t * account)
+{
+ TRACE_START(xact_text, 1, "Time spent parsing transaction text:");
+
+ std::auto_ptr<xact_t> xact(new xact_t);
+
+ xact->pos = position_t();
+ xact->pos->pathname = pathname;
+ xact->pos->beg_pos = line_beg_pos;
+ xact->pos->beg_line = linenum;
+
+ bool reveal_context = true;
+
+ try {
+
+ // Parse the date
+
+ char * next = next_element(line);
+
+ if (char * p = std::strchr(line, '=')) {
+ *p++ = '\0';
+ xact->_date_eff = parse_date(p, current_year);
+ }
+ xact->_date = parse_date(line, current_year);
+
+ // Parse the optional cleared flag: *
+
+ if (next) {
+ switch (*next) {
+ case '*':
+ xact->_state = item_t::CLEARED;
+ next = skip_ws(++next);
+ break;
+ case '!':
+ xact->_state = item_t::PENDING;
+ next = skip_ws(++next);
+ break;
+ }
+ }
+
+ // Parse the optional code: (TEXT)
+
+ if (next && *next == '(') {
+ if (char * p = std::strchr(next++, ')')) {
+ *p++ = '\0';
+ xact->code = next;
+ next = skip_ws(p);
+ }
+ }
+
+ // Parse the description text
+
+ if (next && *next) {
+ char * p = next_element(next, true);
+ xact->payee = next;
+ next = p;
+ } else {
+ xact->payee = _("<Unspecified payee>");
+ }
+
+ // Parse the xact note
+
+ if (next && *next == ';')
+ xact->append_note(++next, current_year);
+
+ TRACE_STOP(xact_text, 1);
+
+ // Parse all of the posts associated with this xact
+
+ TRACE_START(xact_details, 1, "Time spent parsing transaction details:");
+
+ post_t * last_post = NULL;
+
+ while (peek_whitespace_line()) {
+ len = read_line(line);
+
+ char * p = skip_ws(line);
+ if (! *p)
+ break;
+
+ if (*p == ';') {
+ item_t * item;
+ if (last_post)
+ item = last_post;
+ else
+ item = xact.get();
+
+ // This is a trailing note, and possibly a metadata info tag
+ item->append_note(p + 1, current_year);
+ item->pos->end_pos = curr_pos;
+ item->pos->end_line++;
+ } else {
+ reveal_context = false;
+
+ if (post_t * post =
+ parse_post(p, len - (p - line), account, xact.get())) {
+ xact->add_post(post);
+ last_post = post;
+ }
+ }
+ }
+
+ if (xact->_state == item_t::UNCLEARED) {
+ item_t::state_t result = item_t::CLEARED;
+
+ foreach (post_t * post, xact->posts) {
+ if (post->_state == item_t::UNCLEARED) {
+ result = item_t::UNCLEARED;
+ break;
+ }
+ else if (post->_state == item_t::PENDING) {
+ result = item_t::PENDING;
+ }
+ }
+ }
+
+ xact->pos->end_pos = curr_pos;
+ xact->pos->end_line = linenum;
+
+ if (! state_stack.empty()) {
+ foreach (const state_t& state, state_stack)
+ if (state.type() == typeid(string))
+ xact->parse_tags(boost::get<string>(state).c_str());
+ }
+
+ TRACE_STOP(xact_details, 1);
+
+ return xact.release();
+
+ }
+ catch (const std::exception& err) {
+ if (reveal_context) {
+ add_error_context(_("While parsing transaction:"));
+ add_error_context(source_context(xact->pos->pathname,
+ xact->pos->beg_pos, curr_pos, "> "));
+ }
+ throw;
+ }
+}
+
+expr_t::ptr_op_t instance_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
+{
+ return scope.lookup(kind, name);
+}
+
+std::size_t journal_t::parse(std::istream& in,
+ scope_t& scope,
+ account_t * master,
+ const path * original_file,
+ bool strict)
+{
+ TRACE_START(parsing_total, 1, "Total time spent parsing text:");
+
+ std::list<instance_t::state_t> state_stack;
+#if defined(TIMELOG_SUPPORT)
+ time_log_t timelog(*this);
+#endif
+
+ instance_t parsing_instance(state_stack,
+#if defined(TIMELOG_SUPPORT)
+ timelog,
+#endif
+ in, scope, *this, master,
+ original_file, strict);
+ parsing_instance.parse();
+
+ TRACE_STOP(parsing_total, 1);
+
+ // These tracers were started in textual.cc
+ TRACE_FINISH(xact_text, 1);
+ TRACE_FINISH(xact_details, 1);
+ TRACE_FINISH(xact_posts, 1);
+ TRACE_FINISH(xacts, 1);
+ TRACE_FINISH(instance_parse, 1); // report per-instance timers
+ TRACE_FINISH(parsing_total, 1);
+
+ if (parsing_instance.errors > 0)
+ throw static_cast<int>(parsing_instance.errors);
+
+ return parsing_instance.count;
+}
+
+} // namespace ledger
diff --git a/src/timelog.cc b/src/timelog.cc
new file mode 100644
index 00000000..25bf8e94
--- /dev/null
+++ b/src/timelog.cc
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "timelog.h"
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "journal.h"
+
+namespace ledger {
+
+namespace {
+ void clock_out_from_timelog(std::list<time_xact_t>& time_xacts,
+ time_xact_t out_event,
+ journal_t& journal)
+ {
+ time_xact_t event;
+
+ if (time_xacts.size() == 1) {
+ event = time_xacts.back();
+ time_xacts.clear();
+ }
+ else if (time_xacts.empty()) {
+ throw parse_error(_("Timelog check-out event without a check-in"));
+ }
+ else if (! out_event.account) {
+ throw parse_error
+ (_("When multiple check-ins are active, checking out requires an account"));
+ }
+ else {
+ bool found = false;
+
+ for (std::list<time_xact_t>::iterator i = time_xacts.begin();
+ i != time_xacts.end();
+ i++)
+ if (out_event.account == (*i).account) {
+ event = *i;
+ found = true;
+ time_xacts.erase(i);
+ break;
+ }
+
+ if (! found)
+ throw parse_error
+ (_("Timelog check-out event does not match any current check-ins"));
+ }
+
+ if (out_event.checkin < event.checkin)
+ throw parse_error
+ (_("Timelog check-out date less than corresponding check-in"));
+
+ if (! out_event.desc.empty() && event.desc.empty()) {
+ event.desc = out_event.desc;
+ out_event.desc = empty_string;
+ }
+
+ if (! out_event.note.empty() && event.note.empty())
+ event.note = out_event.note;
+
+ std::auto_ptr<xact_t> curr(new xact_t);
+ curr->_date = out_event.checkin.date();
+ curr->code = out_event.desc; // if it wasn't used above
+ curr->payee = event.desc;
+ curr->pos = event.position;
+
+ if (! event.note.empty())
+ curr->append_note(event.note.c_str());
+
+ char buf[32];
+ std::sprintf(buf, "%lds", long((out_event.checkin - event.checkin)
+ .total_seconds()));
+ amount_t amt;
+ amt.parse(buf);
+ VERIFY(amt.valid());
+
+ post_t * post = new post_t(event.account, amt, POST_VIRTUAL);
+ post->set_state(item_t::CLEARED);
+ post->pos = event.position;
+ curr->add_post(post);
+ event.account->add_post(post);
+
+ if (! journal.add_xact(curr.get()))
+ throw parse_error(_("Failed to record 'out' timelog transaction"));
+ else
+ curr.release();
+ }
+} // unnamed namespace
+
+time_log_t::~time_log_t()
+{
+ TRACE_DTOR(time_log_t);
+
+ if (! time_xacts.empty()) {
+ std::list<account_t *> accounts;
+
+ foreach (time_xact_t& time_xact, time_xacts)
+ accounts.push_back(time_xact.account);
+
+ foreach (account_t * account, accounts)
+ clock_out_from_timelog(time_xacts,
+ time_xact_t(none, CURRENT_TIME(), account),
+ journal);
+
+ assert(time_xacts.empty());
+ }
+}
+
+void time_log_t::clock_in(time_xact_t event)
+{
+ if (! time_xacts.empty()) {
+ foreach (time_xact_t& time_xact, time_xacts) {
+ if (event.account == time_xact.account)
+ throw parse_error(_("Cannot double check-in to the same account"));
+ }
+ }
+
+ time_xacts.push_back(event);
+}
+
+void time_log_t::clock_out(time_xact_t event)
+{
+ if (time_xacts.empty())
+ throw std::logic_error(_("Timelog check-out event without a check-in"));
+
+ clock_out_from_timelog(time_xacts, event, journal);
+}
+
+} // namespace ledger
diff --git a/src/timelog.h b/src/timelog.h
new file mode 100644
index 00000000..83256dfa
--- /dev/null
+++ b/src/timelog.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup data
+ */
+
+/**
+ * @file timelog.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _TIMELOG_H
+#define _TIMELOG_H
+
+#include "utils.h"
+#include "times.h"
+#include "item.h"
+
+namespace ledger {
+
+class account_t;
+class journal_t;
+
+class time_xact_t
+{
+public:
+ datetime_t checkin;
+ account_t * account;
+ string desc;
+ string note;
+ position_t position;
+
+ time_xact_t() : account(NULL) {
+ TRACE_CTOR(time_xact_t, "");
+ }
+ time_xact_t(const optional<position_t>& _position,
+ const datetime_t& _checkin,
+ account_t * _account = NULL,
+ const string& _desc = "",
+ const string& _note = "")
+ : checkin(_checkin), account(_account), desc(_desc), note(_note),
+ position(_position ? *_position : position_t()) {
+ TRACE_CTOR(time_xact_t,
+ "position_t, datetime_t, account_t *, string, string");
+ }
+ time_xact_t(const time_xact_t& xact)
+ : checkin(xact.checkin), account(xact.account),
+ desc(xact.desc), note(xact.note), position(xact.position) {
+ TRACE_CTOR(time_xact_t, "copy");
+ }
+ ~time_xact_t() throw() {
+ TRACE_DTOR(time_xact_t);
+ }
+};
+
+class time_log_t
+{
+ std::list<time_xact_t> time_xacts;
+ journal_t& journal;
+
+public:
+ time_log_t(journal_t& _journal) : journal(_journal) {
+ TRACE_CTOR(time_log_t, "journal_t&");
+ }
+ ~time_log_t();
+
+ void clock_in(time_xact_t event);
+ void clock_out(time_xact_t event);
+};
+
+} // namespace ledger
+
+#endif // _TIMELOG_H
diff --git a/src/times.cc b/src/times.cc
new file mode 100644
index 00000000..d4317509
--- /dev/null
+++ b/src/times.cc
@@ -0,0 +1,1587 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "times.h"
+
+namespace ledger {
+
+optional<datetime_t> epoch;
+
+date_time::weekdays start_of_week = gregorian::Sunday;
+
+//#define USE_BOOST_FACETS 1
+
+namespace {
+ template <typename T, typename InputFacetType, typename OutputFacetType>
+ class temporal_io_t : public noncopyable
+ {
+ const char * fmt_str;
+#if defined(USE_BOOST_FACETS)
+ std::istringstream input_stream;
+ std::ostringstream output_stream;
+ InputFacetType * input_facet;
+ OutputFacetType * output_facet;
+ std::string temp_string;
+#endif // USE_BOOST_FACETS
+
+ public:
+ date_traits_t traits;
+ bool input;
+
+ temporal_io_t(const char * _fmt_str, bool _input)
+ : fmt_str(_fmt_str),
+ traits(icontains(fmt_str, "%y"),
+ icontains(fmt_str, "%m") || icontains(fmt_str, "%b"),
+ icontains(fmt_str, "%d")),
+ input(_input) {
+#if defined(USE_BOOST_FACETS)
+ if (input) {
+ input_facet = new InputFacetType(fmt_str);
+ input_stream.imbue(std::locale(std::locale::classic(), input_facet));
+ } else {
+ output_facet = new OutputFacetType(fmt_str);
+ output_stream.imbue(std::locale(std::locale::classic(), output_facet));
+ }
+#endif // USE_BOOST_FACETS
+ }
+
+ void set_format(const char * fmt) {
+ fmt_str = fmt;
+ traits = date_traits_t(icontains(fmt_str, "%y"),
+ icontains(fmt_str, "%m") ||
+ icontains(fmt_str, "%b"),
+ icontains(fmt_str, "%d"));
+#if defined(USE_BOOST_FACETS)
+ if (input)
+ input_facet->format(fmt_str);
+ else
+ output_facet->format(fmt_str);
+#endif // USE_BOOST_FACETS
+ }
+
+ T parse(const char * str) {
+ }
+
+ std::string format(const T& when) {
+#if defined(USE_BOOST_FACETS)
+ output_stream.str(temp_string);
+ output_stream.seekp(std::ios_base::beg);
+ output_stream.clear();
+ output_stream << when;
+ return output_stream.str();
+#else // USE_BOOST_FACETS
+ std::tm data(to_tm(when));
+ char buf[128];
+ std::strftime(buf, 127, fmt_str, &data);
+ return buf;
+#endif // USE_BOOST_FACETS
+ }
+ };
+
+ template <>
+ datetime_t temporal_io_t<datetime_t, posix_time::time_input_facet,
+ posix_time::time_facet>
+ ::parse(const char * str)
+ {
+#if defined(USE_BOOST_FACETS)
+ input_stream.seekg(std::ios_base::beg);
+ input_stream.clear();
+ input_stream.str(str);
+
+ datetime_t when;
+ input_stream >> when;
+#if defined(DEBUG_ON)
+ if (when.is_not_a_date_time())
+ DEBUG("times.parse", "Failed to parse date/time '" << str
+ << "' using pattern '" << fmt_str << "'");
+#endif
+
+ if (! when.is_not_a_date_time() &&
+ input_stream.good() && ! input_stream.eof() &&
+ input_stream.peek() != EOF) {
+ DEBUG("times.parse", "This string has leftovers: '" << str << "'");
+ return datetime_t();
+ }
+ return when;
+#else // USE_BOOST_FACETS
+ std::tm data;
+ std::memset(&data, 0, sizeof(std::tm));
+ if (strptime(str, fmt_str, &data))
+ return posix_time::ptime_from_tm(data);
+ else
+ return datetime_t();
+#endif // USE_BOOST_FACETS
+ }
+
+ template <>
+ date_t temporal_io_t<date_t, gregorian::date_input_facet,
+ gregorian::date_facet>
+ ::parse(const char * str)
+ {
+#if defined(USE_BOOST_FACETS)
+ input_stream.seekg(std::ios_base::beg);
+ input_stream.clear();
+ input_stream.str(str);
+
+ date_t when;
+ input_stream >> when;
+#if defined(DEBUG_ON)
+ if (when.is_not_a_date())
+ DEBUG("times.parse", "Failed to parse date '" << str
+ << "' using pattern '" << fmt_str << "'");
+#endif
+
+ if (! when.is_not_a_date() &&
+ input_stream.good() && ! input_stream.eof() &&
+ input_stream.peek() != EOF) {
+ DEBUG("times.parse", "This string has leftovers: '" << str << "'");
+ return date_t();
+ }
+ return when;
+#else // USE_BOOST_FACETS
+ std::tm data;
+ std::memset(&data, 0, sizeof(std::tm));
+ data.tm_mday = 1; // some formats have no day
+ if (strptime(str, fmt_str, &data))
+ return gregorian::date_from_tm(data);
+ else
+ return date_t();
+#endif // USE_BOOST_FACETS
+ }
+
+ typedef temporal_io_t<datetime_t, posix_time::time_input_facet,
+ posix_time::time_facet> datetime_io_t;
+ typedef temporal_io_t<date_t, gregorian::date_input_facet,
+ gregorian::date_facet> date_io_t;
+
+ shared_ptr<datetime_io_t> input_datetime_io;
+ shared_ptr<date_io_t> input_date_io;
+ shared_ptr<datetime_io_t> written_datetime_io;
+ shared_ptr<date_io_t> written_date_io;
+ shared_ptr<datetime_io_t> printed_datetime_io;
+ shared_ptr<date_io_t> printed_date_io;
+
+ std::vector<shared_ptr<date_io_t> > readers;
+
+ date_t parse_date_mask_routine(const char * date_str, date_io_t& io,
+ optional_year year,
+ date_traits_t * traits = NULL)
+ {
+ date_t when;
+
+ if (std::strchr(date_str, '/')) {
+ when = io.parse(date_str);
+ } else {
+ char buf[128];
+ VERIFY(std::strlen(date_str) < 127);
+ std::strcpy(buf, date_str);
+
+ for (char * p = buf; *p; p++)
+ if (*p == '.' || *p == '-')
+ *p = '/';
+
+ when = io.parse(buf);
+ }
+
+ if (! when.is_not_a_date()) {
+ DEBUG("times.parse", "Parsed date string: " << date_str);
+ DEBUG("times.parse", "Parsed result is: " << when);
+
+ if (traits)
+ *traits = io.traits;
+
+ if (! io.traits.has_year) {
+ when = date_t(year ? *year : CURRENT_DATE().year(),
+ when.month(), when.day());
+
+ if (when.month() > CURRENT_DATE().month())
+ when -= gregorian::years(1);
+ }
+ }
+ return when;
+ }
+
+ date_t parse_date_mask(const char * date_str, optional_year year,
+ date_traits_t * traits = NULL)
+ {
+ if (input_date_io.get()) {
+ date_t when = parse_date_mask_routine(date_str, *input_date_io.get(),
+ year, traits);
+ if (! when.is_not_a_date())
+ return when;
+ }
+
+ foreach (shared_ptr<date_io_t>& reader, readers) {
+ date_t when = parse_date_mask_routine(date_str, *reader.get(),
+ year, traits);
+ if (! when.is_not_a_date())
+ return when;
+ }
+
+ throw_(date_error, _("Invalid date: %1") << date_str);
+ return date_t();
+ }
+}
+
+optional<date_time::weekdays> string_to_day_of_week(const std::string& str)
+{
+ if (str == _("sun") || str == _("sunday") || str == "0")
+ return gregorian::Sunday;
+ else if (str == _("mon") || str == _("monday") || str == "1")
+ return gregorian::Monday;
+ else if (str == _("tue") || str == _("tuesday") || str == "2")
+ return gregorian::Tuesday;
+ else if (str == _("wed") || str == _("wednesday") || str == "3")
+ return gregorian::Wednesday;
+ else if (str == _("thu") || str == _("thursday") || str == "4")
+ return gregorian::Thursday;
+ else if (str == _("fri") || str == _("friday") || str == "5")
+ return gregorian::Friday;
+ else if (str == _("sat") || str == _("saturday") || str == "6")
+ return gregorian::Saturday;
+ else
+ return none;
+}
+
+optional<date_time::months_of_year>
+string_to_month_of_year(const std::string& str)
+{
+ if (str == _("jan") || str == _("january") || str == "0")
+ return gregorian::Jan;
+ else if (str == _("feb") || str == _("february") || str == "1")
+ return gregorian::Feb;
+ else if (str == _("mar") || str == _("march") || str == "2")
+ return gregorian::Mar;
+ else if (str == _("apr") || str == _("april") || str == "3")
+ return gregorian::Apr;
+ else if (str == _("may") || str == _("may") || str == "4")
+ return gregorian::May;
+ else if (str == _("jun") || str == _("june") || str == "5")
+ return gregorian::Jun;
+ else if (str == _("jul") || str == _("july") || str == "6")
+ return gregorian::Jul;
+ else if (str == _("aug") || str == _("august") || str == "7")
+ return gregorian::Aug;
+ else if (str == _("sep") || str == _("september") || str == "8")
+ return gregorian::Sep;
+ else if (str == _("oct") || str == _("october") || str == "9")
+ return gregorian::Oct;
+ else if (str == _("nov") || str == _("november") || str == "10")
+ return gregorian::Nov;
+ else if (str == _("dec") || str == _("december") || str == "11")
+ return gregorian::Dec;
+ else
+ return none;
+}
+
+datetime_t parse_datetime(const char * str, optional_year)
+{
+ datetime_t when = input_datetime_io->parse(str);
+ if (when.is_not_a_date_time())
+ throw_(date_error, _("Invalid date/time: %1") << str);
+ return when;
+}
+
+date_t parse_date(const char * str, optional_year current_year)
+{
+ return parse_date_mask(str, current_year);
+}
+
+date_t date_specifier_t::begin(const optional_year& current_year) const
+{
+ assert(year || current_year);
+
+ year_type the_year = year ? *year : static_cast<year_type>(*current_year);
+ month_type the_month = month ? *month : date_t::month_type(1);
+ day_type the_day = day ? *day : date_t::day_type(1);
+
+ if (day)
+ assert(! wday);
+ else if (wday)
+ assert(! day);
+
+ // jww (2009-11-16): Handle wday. If a month is set, find the most recent
+ // wday in that month; if the year is set, then in that year.
+
+ return gregorian::date(static_cast<date_t::year_type>(the_year),
+ static_cast<date_t::month_type>(the_month),
+ static_cast<date_t::day_type>(the_day));
+}
+
+date_t date_specifier_t::end(const optional_year& current_year) const
+{
+ if (day || wday)
+ return begin(current_year) + gregorian::days(1);
+ else if (month)
+ return begin(current_year) + gregorian::months(1);
+ else if (year)
+ return begin(current_year) + gregorian::years(1);
+ else {
+ assert(false);
+ return date_t();
+ }
+}
+
+std::ostream& operator<<(std::ostream& out,
+ const date_duration_t& duration)
+{
+ if (duration.quantum == date_duration_t::DAYS)
+ out << duration.length << " day(s)";
+ else if (duration.quantum == date_duration_t::WEEKS)
+ out << duration.length << " week(s)";
+ else if (duration.quantum == date_duration_t::MONTHS)
+ out << duration.length << " month(s)";
+ else if (duration.quantum == date_duration_t::QUARTERS)
+ out << duration.length << " quarter(s)";
+ else {
+ assert(duration.quantum == date_duration_t::YEARS);
+ out << duration.length << " year(s)";
+ }
+ return out;
+}
+
+class date_parser_t
+{
+ friend void show_period_tokens(std::ostream& out, const string& arg);
+
+ class lexer_t
+ {
+ friend class date_parser_t;
+
+ string::const_iterator begin;
+ string::const_iterator end;
+
+ public:
+ struct token_t
+ {
+ enum kind_t {
+ UNKNOWN,
+
+ TOK_DATE,
+ TOK_INT,
+ TOK_SLASH,
+ TOK_DASH,
+ TOK_DOT,
+
+ TOK_A_YEAR,
+ TOK_A_MONTH,
+ TOK_A_WDAY,
+
+ TOK_SINCE,
+ TOK_UNTIL,
+ TOK_IN,
+ TOK_THIS,
+ TOK_NEXT,
+ TOK_LAST,
+ TOK_EVERY,
+
+ TOK_TODAY,
+ TOK_TOMORROW,
+ TOK_YESTERDAY,
+
+ TOK_YEAR,
+ TOK_QUARTER,
+ TOK_MONTH,
+ TOK_WEEK,
+ TOK_DAY,
+
+ TOK_YEARLY,
+ TOK_QUARTERLY,
+ TOK_BIMONTHLY,
+ TOK_MONTHLY,
+ TOK_BIWEEKLY,
+ TOK_WEEKLY,
+ TOK_DAILY,
+
+ TOK_YEARS,
+ TOK_QUARTERS,
+ TOK_MONTHS,
+ TOK_WEEKS,
+ TOK_DAYS,
+
+ END_REACHED
+
+ } kind;
+
+ typedef variant<unsigned short,
+ string,
+ date_specifier_t::year_type,
+ date_time::months_of_year,
+ date_time::weekdays,
+ date_specifier_t> content_t;
+
+ optional<content_t> value;
+
+ explicit token_t(kind_t _kind = UNKNOWN,
+ const optional<content_t>& _value =
+ content_t(empty_string))
+ : kind(_kind), value(_value) {
+ TRACE_CTOR(date_parser_t::lexer_t::token_t, "");
+ }
+ token_t(const token_t& tok)
+ : kind(tok.kind), value(tok.value) {
+ TRACE_CTOR(date_parser_t::lexer_t::token_t, "copy");
+ }
+ ~token_t() throw() {
+ TRACE_DTOR(date_parser_t::lexer_t::token_t);
+ }
+
+ token_t& operator=(const token_t& tok) {
+ if (this != &tok) {
+ kind = tok.kind;
+ value = tok.value;
+ }
+ return *this;
+ }
+
+ operator bool() const {
+ return kind != END_REACHED;
+ }
+
+ string to_string() const {
+ std::ostringstream out;
+
+ switch (kind) {
+ case UNKNOWN:
+ out << boost::get<string>(*value);
+ break;
+ case TOK_DATE:
+ return boost::get<date_specifier_t>(*value).to_string();
+ case TOK_INT:
+ out << boost::get<unsigned short>(*value);
+ break;
+ case TOK_SLASH: return "/";
+ case TOK_DASH: return "-";
+ case TOK_DOT: return ".";
+ case TOK_A_YEAR:
+ out << boost::get<date_specifier_t::year_type>(*value);
+ break;
+ case TOK_A_MONTH:
+ out << date_specifier_t::month_type
+ (boost::get<date_time::months_of_year>(*value));
+ break;
+ case TOK_A_WDAY:
+ out << date_specifier_t::day_of_week_type
+ (boost::get<date_time::weekdays>(*value));
+ break;
+ case TOK_SINCE: return "since";
+ case TOK_UNTIL: return "until";
+ case TOK_IN: return "in";
+ case TOK_THIS: return "this";
+ case TOK_NEXT: return "next";
+ case TOK_LAST: return "last";
+ case TOK_EVERY: return "every";
+ case TOK_TODAY: return "today";
+ case TOK_TOMORROW: return "tomorrow";
+ case TOK_YESTERDAY: return "yesterday";
+ case TOK_YEAR: return "year";
+ case TOK_QUARTER: return "quarter";
+ case TOK_MONTH: return "month";
+ case TOK_WEEK: return "week";
+ case TOK_DAY: return "day";
+ case TOK_YEARLY: return "yearly";
+ case TOK_QUARTERLY: return "quarterly";
+ case TOK_BIMONTHLY: return "bimonthly";
+ case TOK_MONTHLY: return "monthly";
+ case TOK_BIWEEKLY: return "biweekly";
+ case TOK_WEEKLY: return "weekly";
+ case TOK_DAILY: return "daily";
+ case TOK_YEARS: return "years";
+ case TOK_QUARTERS: return "quarters";
+ case TOK_MONTHS: return "months";
+ case TOK_WEEKS: return "weeks";
+ case TOK_DAYS: return "days";
+ case END_REACHED: return "<EOF>";
+ default:
+ assert(false);
+ return empty_string;
+ }
+
+ return out.str();
+ }
+
+ void dump(std::ostream& out) const {
+ switch (kind) {
+ case UNKNOWN: out << "UNKNOWN"; break;
+ case TOK_DATE: out << "TOK_DATE"; break;
+ case TOK_INT: out << "TOK_INT"; break;
+ case TOK_SLASH: out << "TOK_SLASH"; break;
+ case TOK_DASH: out << "TOK_DASH"; break;
+ case TOK_DOT: out << "TOK_DOT"; break;
+ case TOK_A_YEAR: out << "TOK_A_YEAR"; break;
+ case TOK_A_MONTH: out << "TOK_A_MONTH"; break;
+ case TOK_A_WDAY: out << "TOK_A_WDAY"; break;
+ case TOK_SINCE: out << "TOK_SINCE"; break;
+ case TOK_UNTIL: out << "TOK_UNTIL"; break;
+ case TOK_IN: out << "TOK_IN"; break;
+ case TOK_THIS: out << "TOK_THIS"; break;
+ case TOK_NEXT: out << "TOK_NEXT"; break;
+ case TOK_LAST: out << "TOK_LAST"; break;
+ case TOK_EVERY: out << "TOK_EVERY"; break;
+ case TOK_TODAY: out << "TOK_TODAY"; break;
+ case TOK_TOMORROW: out << "TOK_TOMORROW"; break;
+ case TOK_YESTERDAY: out << "TOK_YESTERDAY"; break;
+ case TOK_YEAR: out << "TOK_YEAR"; break;
+ case TOK_QUARTER: out << "TOK_QUARTER"; break;
+ case TOK_MONTH: out << "TOK_MONTH"; break;
+ case TOK_WEEK: out << "TOK_WEEK"; break;
+ case TOK_DAY: out << "TOK_DAY"; break;
+ case TOK_YEARLY: out << "TOK_YEARLY"; break;
+ case TOK_QUARTERLY: out << "TOK_QUARTERLY"; break;
+ case TOK_BIMONTHLY: out << "TOK_BIMONTHLY"; break;
+ case TOK_MONTHLY: out << "TOK_MONTHLY"; break;
+ case TOK_BIWEEKLY: out << "TOK_BIWEEKLY"; break;
+ case TOK_WEEKLY: out << "TOK_WEEKLY"; break;
+ case TOK_DAILY: out << "TOK_DAILY"; break;
+ case TOK_YEARS: out << "TOK_YEARS"; break;
+ case TOK_QUARTERS: out << "TOK_QUARTERS"; break;
+ case TOK_MONTHS: out << "TOK_MONTHS"; break;
+ case TOK_WEEKS: out << "TOK_WEEKS"; break;
+ case TOK_DAYS: out << "TOK_DAYS"; break;
+ case END_REACHED: out << "END_REACHED"; break;
+ default:
+ assert(false);
+ break;
+ }
+ }
+
+ void unexpected();
+ static void expected(char wanted, char c = '\0');
+ };
+
+ token_t token_cache;
+
+ lexer_t(string::const_iterator _begin,
+ string::const_iterator _end)
+ : begin(_begin), end(_end)
+ {
+ TRACE_CTOR(date_parser_t::lexer_t, "");
+ }
+ lexer_t(const lexer_t& lexer)
+ : begin(lexer.begin), end(lexer.end),
+ token_cache(lexer.token_cache)
+ {
+ TRACE_CTOR(date_parser_t::lexer_t, "copy");
+ }
+ ~lexer_t() throw() {
+ TRACE_DTOR(date_parser_t::lexer_t);
+ }
+
+ token_t next_token();
+ void push_token(token_t tok) {
+ assert(token_cache.kind == token_t::UNKNOWN);
+ token_cache = tok;
+ }
+ token_t peek_token() {
+ if (token_cache.kind == token_t::UNKNOWN)
+ token_cache = next_token();
+ return token_cache;
+ }
+ };
+
+ string arg;
+ lexer_t lexer;
+
+public:
+ date_parser_t(const string& _arg)
+ : arg(_arg), lexer(arg.begin(), arg.end()) {
+ TRACE_CTOR(date_parser_t, "");
+ }
+ date_parser_t(const date_parser_t& parser)
+ : arg(parser.arg), lexer(parser.lexer) {
+ TRACE_CTOR(date_parser_t, "copy");
+ }
+ ~date_parser_t() throw() {
+ TRACE_DTOR(date_parser_t);
+ }
+
+ date_interval_t parse();
+
+private:
+ void determine_when(lexer_t::token_t& tok, date_specifier_t& specifier);
+};
+
+void date_parser_t::determine_when(date_parser_t::lexer_t::token_t& tok,
+ date_specifier_t& specifier)
+{
+ switch (tok.kind) {
+ case lexer_t::token_t::TOK_DATE:
+ specifier = boost::get<date_specifier_t>(*tok.value);
+ break;
+
+ case lexer_t::token_t::TOK_INT:
+ specifier.day =
+ date_specifier_t::day_type(boost::get<unsigned short>(*tok.value));
+ break;
+ case lexer_t::token_t::TOK_A_YEAR:
+ specifier.year = boost::get<date_specifier_t::year_type>(*tok.value);
+ break;
+ case lexer_t::token_t::TOK_A_MONTH:
+ specifier.month =
+ date_specifier_t::month_type
+ (boost::get<date_time::months_of_year>(*tok.value));
+ break;
+ case lexer_t::token_t::TOK_A_WDAY:
+ specifier.wday =
+ date_specifier_t::day_of_week_type
+ (boost::get<date_time::weekdays>(*tok.value));
+ break;
+
+ default:
+ tok.unexpected();
+ break;
+ }
+}
+
+date_interval_t date_parser_t::parse()
+{
+ optional<date_specifier_t> since_specifier;
+ optional<date_specifier_t> until_specifier;
+ optional<date_specifier_t> inclusion_specifier;
+
+ date_interval_t period;
+ date_t today = CURRENT_DATE();
+ bool end_inclusive = false;
+
+ for (lexer_t::token_t tok = lexer.next_token();
+ tok.kind != lexer_t::token_t::END_REACHED;
+ tok = lexer.next_token()) {
+ switch (tok.kind) {
+#if 0
+ case lexer_t::token_t::TOK_INT:
+ // jww (2009-11-18): NYI
+ assert(! "Need to allow for expressions like \"4 months ago\"");
+ tok.unexpected();
+ break;
+#endif
+
+ case lexer_t::token_t::TOK_DATE:
+ if (! inclusion_specifier)
+ inclusion_specifier = date_specifier_t();
+ determine_when(tok, *inclusion_specifier);
+ break;
+
+ case lexer_t::token_t::TOK_INT:
+ if (! inclusion_specifier)
+ inclusion_specifier = date_specifier_t();
+ determine_when(tok, *inclusion_specifier);
+ break;
+
+ case lexer_t::token_t::TOK_A_YEAR:
+ if (! inclusion_specifier)
+ inclusion_specifier = date_specifier_t();
+ determine_when(tok, *inclusion_specifier);
+ break;
+
+ case lexer_t::token_t::TOK_A_MONTH:
+ if (! inclusion_specifier)
+ inclusion_specifier = date_specifier_t();
+ determine_when(tok, *inclusion_specifier);
+ break;
+
+ case lexer_t::token_t::TOK_A_WDAY:
+ if (! inclusion_specifier)
+ inclusion_specifier = date_specifier_t();
+ determine_when(tok, *inclusion_specifier);
+ break;
+
+ case lexer_t::token_t::TOK_DASH:
+ if (inclusion_specifier) {
+ since_specifier = inclusion_specifier;
+ until_specifier = date_specifier_t();
+ inclusion_specifier = none;
+
+ tok = lexer.next_token();
+ determine_when(tok, *until_specifier);
+
+ // The dash operator is special: it has an _inclusive_ end.
+ end_inclusive = true;
+ } else {
+ tok.unexpected();
+ }
+ break;
+
+ case lexer_t::token_t::TOK_SINCE:
+ if (since_specifier) {
+ tok.unexpected();
+ } else {
+ since_specifier = date_specifier_t();
+ tok = lexer.next_token();
+ determine_when(tok, *since_specifier);
+ }
+ break;
+
+ case lexer_t::token_t::TOK_UNTIL:
+ if (until_specifier) {
+ tok.unexpected();
+ } else {
+ until_specifier = date_specifier_t();
+ tok = lexer.next_token();
+ determine_when(tok, *until_specifier);
+ }
+ break;
+
+ case lexer_t::token_t::TOK_IN:
+ if (inclusion_specifier) {
+ tok.unexpected();
+ } else {
+ inclusion_specifier = date_specifier_t();
+ tok = lexer.next_token();
+ determine_when(tok, *inclusion_specifier);
+ }
+ break;
+
+ case lexer_t::token_t::TOK_THIS:
+ case lexer_t::token_t::TOK_NEXT:
+ case lexer_t::token_t::TOK_LAST: {
+ int8_t adjust = 0;
+ if (tok.kind == lexer_t::token_t::TOK_NEXT)
+ adjust = 1;
+ else if (tok.kind == lexer_t::token_t::TOK_LAST)
+ adjust = -1;
+
+ tok = lexer.next_token();
+ switch (tok.kind) {
+ case lexer_t::token_t::TOK_INT:
+ // jww (2009-11-18): Allow things like "last 5 weeks"
+ assert(! "Need to allow for expressions like \"last 5 weeks\"");
+ tok.unexpected();
+ break;
+
+ case lexer_t::token_t::TOK_A_MONTH: {
+ inclusion_specifier = date_specifier_t();
+ determine_when(tok, *inclusion_specifier);
+
+ date_t temp(today.year(), *inclusion_specifier->month, 1);
+ temp += gregorian::years(adjust);
+ inclusion_specifier =
+ date_specifier_t(static_cast<date_specifier_t::year_type>(temp.year()),
+ temp.month());
+ break;
+ }
+
+ case lexer_t::token_t::TOK_A_WDAY: {
+ inclusion_specifier = date_specifier_t();
+ determine_when(tok, *inclusion_specifier);
+
+ date_t temp =
+ date_duration_t::find_nearest(today, date_duration_t::WEEKS);
+ while (temp.day_of_week() != inclusion_specifier->wday)
+ temp += gregorian::days(1);
+ temp += gregorian::days(7 * adjust);
+ inclusion_specifier = date_specifier_t(temp);
+ break;
+ }
+
+ case lexer_t::token_t::TOK_YEAR: {
+ date_t temp(today);
+ temp += gregorian::years(adjust);
+ inclusion_specifier =
+ date_specifier_t(static_cast<date_specifier_t::year_type>(temp.year()));
+ break;
+ }
+
+ case lexer_t::token_t::TOK_QUARTER: {
+ date_t temp =
+ date_duration_t::find_nearest(today, date_duration_t::QUARTERS);
+ temp += gregorian::months(3 * adjust);
+ inclusion_specifier =
+ date_specifier_t(static_cast<date_specifier_t::year_type>(temp.year()),
+ temp.month());
+#if 0
+ period.duration = date_duration_t(date_duration_t::QUARTERS, 1);
+#endif
+ break;
+ }
+
+ case lexer_t::token_t::TOK_MONTH: {
+ date_t temp(today);
+ temp += gregorian::months(adjust);
+ inclusion_specifier =
+ date_specifier_t(static_cast<date_specifier_t::year_type>(temp.year()),
+ temp.month());
+ break;
+ }
+
+ case lexer_t::token_t::TOK_WEEK: {
+ date_t temp =
+ date_duration_t::find_nearest(today, date_duration_t::WEEKS);
+ temp += gregorian::days(7 * adjust);
+ inclusion_specifier = date_specifier_t(today);
+#if 0
+ period.duration = date_duration_t(date_duration_t::WEEKS, 1);
+#endif
+ break;
+ }
+
+ case lexer_t::token_t::TOK_DAY: {
+ date_t temp(today);
+ temp += gregorian::days(adjust);
+ inclusion_specifier = date_specifier_t(temp);
+ break;
+ }
+
+ default:
+ tok.unexpected();
+ break;
+ }
+ break;
+ }
+
+ case lexer_t::token_t::TOK_TODAY:
+ inclusion_specifier = date_specifier_t(today);
+ break;
+ case lexer_t::token_t::TOK_TOMORROW:
+ inclusion_specifier = date_specifier_t(today + gregorian::days(1));
+ break;
+ case lexer_t::token_t::TOK_YESTERDAY:
+ inclusion_specifier = date_specifier_t(today - gregorian::days(1));
+ break;
+
+ case lexer_t::token_t::TOK_EVERY:
+ tok = lexer.next_token();
+ if (tok == lexer_t::token_t::TOK_INT) {
+ int quantity = boost::get<unsigned short>(*tok.value);
+ tok = lexer.next_token();
+ switch (tok.kind) {
+ case lexer_t::token_t::TOK_YEARS:
+ period.duration = date_duration_t(date_duration_t::YEARS, quantity);
+ break;
+ case lexer_t::token_t::TOK_QUARTERS:
+ period.duration = date_duration_t(date_duration_t::QUARTERS, quantity);
+ break;
+ case lexer_t::token_t::TOK_MONTHS:
+ period.duration = date_duration_t(date_duration_t::MONTHS, quantity);
+ break;
+ case lexer_t::token_t::TOK_WEEKS:
+ period.duration = date_duration_t(date_duration_t::WEEKS, quantity);
+ break;
+ case lexer_t::token_t::TOK_DAYS:
+ period.duration = date_duration_t(date_duration_t::DAYS, quantity);
+ break;
+ default:
+ tok.unexpected();
+ break;
+ }
+ } else {
+ switch (tok.kind) {
+ case lexer_t::token_t::TOK_YEAR:
+ period.duration = date_duration_t(date_duration_t::YEARS, 1);
+ break;
+ case lexer_t::token_t::TOK_QUARTER:
+ period.duration = date_duration_t(date_duration_t::QUARTERS, 1);
+ break;
+ case lexer_t::token_t::TOK_MONTH:
+ period.duration = date_duration_t(date_duration_t::MONTHS, 1);
+ break;
+ case lexer_t::token_t::TOK_WEEK:
+ period.duration = date_duration_t(date_duration_t::WEEKS, 1);
+ break;
+ case lexer_t::token_t::TOK_DAY:
+ period.duration = date_duration_t(date_duration_t::DAYS, 1);
+ break;
+ default:
+ tok.unexpected();
+ break;
+ }
+ }
+ break;
+
+ case lexer_t::token_t::TOK_YEARLY:
+ period.duration = date_duration_t(date_duration_t::YEARS, 1);
+ break;
+ case lexer_t::token_t::TOK_QUARTERLY:
+ period.duration = date_duration_t(date_duration_t::QUARTERS, 1);
+ break;
+ case lexer_t::token_t::TOK_BIMONTHLY:
+ period.duration = date_duration_t(date_duration_t::MONTHS, 2);
+ break;
+ case lexer_t::token_t::TOK_MONTHLY:
+ period.duration = date_duration_t(date_duration_t::MONTHS, 1);
+ break;
+ case lexer_t::token_t::TOK_BIWEEKLY:
+ period.duration = date_duration_t(date_duration_t::WEEKS, 2);
+ break;
+ case lexer_t::token_t::TOK_WEEKLY:
+ period.duration = date_duration_t(date_duration_t::WEEKS, 1);
+ break;
+ case lexer_t::token_t::TOK_DAILY:
+ period.duration = date_duration_t(date_duration_t::DAYS, 1);
+ break;
+
+ default:
+ tok.unexpected();
+ break;
+ }
+ }
+
+#if 0
+ if (! period.duration && inclusion_specifier)
+ period.duration = inclusion_specifier->implied_duration();
+#endif
+
+ if (since_specifier || until_specifier) {
+ date_range_t range(since_specifier, until_specifier);
+ range.end_inclusive = end_inclusive;
+
+ period.range = date_specifier_or_range_t(range);
+ }
+ else if (inclusion_specifier) {
+ period.range = date_specifier_or_range_t(*inclusion_specifier);
+ }
+ else {
+ /* otherwise, it's something like "monthly", with no date reference */
+ }
+
+ return period;
+}
+
+void date_interval_t::parse(const string& str)
+{
+ date_parser_t parser(str);
+ *this = parser.parse();
+}
+
+void date_interval_t::resolve_end()
+{
+ if (start && ! end_of_duration) {
+ end_of_duration = duration->add(*start);
+ DEBUG("times.interval",
+ "stabilize: end_of_duration = " << *end_of_duration);
+ }
+
+ if (finish && *end_of_duration > *finish) {
+ end_of_duration = finish;
+ DEBUG("times.interval",
+ "stabilize: end_of_duration reset to end: " << *end_of_duration);
+ }
+
+ if (start && ! next) {
+ next = end_of_duration;
+ DEBUG("times.interval", "stabilize: next set to: " << *next);
+ }
+}
+
+date_t date_duration_t::find_nearest(const date_t& date, skip_quantum_t skip)
+{
+ date_t result;
+
+ switch (skip) {
+ case date_duration_t::YEARS:
+ result = date_t(date.year(), gregorian::Jan, 1);
+ break;
+ case date_duration_t::QUARTERS:
+ result = date_t(date.year(), date.month(), 1);
+ while (result.month() != gregorian::Jan &&
+ result.month() != gregorian::Apr &&
+ result.month() != gregorian::Jul &&
+ result.month() != gregorian::Oct)
+ result -= gregorian::months(1);
+ break;
+ case date_duration_t::MONTHS:
+ result = date_t(date.year(), date.month(), 1);
+ break;
+ case date_duration_t::WEEKS:
+ result = date;
+ while (result.day_of_week() != start_of_week)
+ result -= gregorian::days(1);
+ break;
+ case date_duration_t::DAYS:
+ result = date;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ return result;
+}
+
+void date_interval_t::stabilize(const optional<date_t>& date)
+{
+#if defined(DEBUG_ON)
+ if (date)
+ DEBUG("times.interval", "stabilize: with date = " << *date);
+#endif
+
+ if (date && ! aligned) {
+ DEBUG("times.interval", "stabilize: date passed, but not aligned");
+ if (duration) {
+ DEBUG("times.interval",
+ "stabilize: aligning with a duration: " << *duration);
+
+ // The interval object has not been seeded with a start date yet, so
+ // find the nearest period before on on date which fits, if possible.
+ //
+ // Find an efficient starting point for the upcoming while loop. We
+ // want a date early enough that the range will be correct, but late
+ // enough that we don't spend hundreds of thousands of loops skipping
+ // through time.
+ optional<date_t> initial_start = start ? start : begin(date->year());
+ optional<date_t> initial_finish = finish ? finish : end(date->year());
+
+#if defined(DEBUG_ON)
+ if (initial_start)
+ DEBUG("times.interval",
+ "stabilize: initial_start = " << *initial_start);
+ if (initial_finish)
+ DEBUG("times.interval",
+ "stabilize: initial_finish = " << *initial_finish);
+#endif
+
+ date_t when = start ? *start : *date;
+
+ if (duration->quantum == date_duration_t::MONTHS ||
+ duration->quantum == date_duration_t::QUARTERS ||
+ duration->quantum == date_duration_t::YEARS) {
+ DEBUG("times.interval",
+ "stabilize: monthly, quarterly or yearly duration");
+ start = date_duration_t::find_nearest(when, duration->quantum);
+ } else {
+ DEBUG("times.interval", "stabilize: daily or weekly duration");
+ start = date_duration_t::find_nearest(when - gregorian::days(400),
+ duration->quantum);
+ }
+
+ DEBUG("times.interval",
+ "stabilize: beginning start date = " << *start);
+
+ while (*start < *date) {
+ date_interval_t next_interval(*this);
+ ++next_interval;
+
+ if (next_interval.start && *next_interval.start < *date) {
+ *this = next_interval;
+ } else {
+ end_of_duration = none;
+ next = none;
+ break;
+ }
+ }
+
+ DEBUG("times.interval", "stabilize: proposed start date = " << *start);
+
+ if (initial_start && (! start || *start < *initial_start)) {
+ // Using the discovered start, find the end of the period
+ resolve_end();
+
+ start = initial_start;
+ DEBUG("times.interval", "stabilize: start reset to initial start");
+ }
+ if (initial_finish && (! finish || *finish > *initial_finish)) {
+ finish = initial_finish;
+ DEBUG("times.interval", "stabilize: finish reset to initial finish");
+ }
+
+#if defined(DEBUG_ON)
+ if (start)
+ DEBUG("times.interval", "stabilize: final start = " << *start);
+ if (finish)
+ DEBUG("times.interval", "stabilize: final finish = " << *finish);
+#endif
+ }
+ else if (range) {
+ if (date) {
+ start = range->begin(date->year());
+ finish = range->end(date->year());
+ } else {
+ start = range->begin();
+ finish = range->end();
+ }
+ }
+ aligned = true;
+ }
+
+ // If there is no duration, then if we've reached here the date falls
+ // between start and finish.
+ if (! duration) {
+ DEBUG("times.interval", "stabilize: there was no duration given");
+
+ if (! start && ! finish)
+ throw_(date_error,
+ _("Invalid date interval: neither start, nor finish, nor duration"));
+ } else {
+ resolve_end();
+ }
+}
+
+bool date_interval_t::find_period(const date_t& date)
+{
+ stabilize(date);
+
+ if (finish && date > *finish) {
+ DEBUG("times.interval",
+ "false: date [" << date << "] > finish [" << *finish << "]");
+ return false;
+ }
+
+ if (! start) {
+ throw_(std::runtime_error, _("Date interval is improperly initialized"));
+ }
+ else if (date < *start) {
+ DEBUG("times.interval",
+ "false: date [" << date << "] < start [" << *start << "]");
+ return false;
+ }
+
+ if (end_of_duration) {
+ if (date < *end_of_duration) {
+ DEBUG("times.interval",
+ "true: date [" << date << "] < end_of_duration ["
+ << *end_of_duration << "]");
+ return true;
+ }
+ } else {
+ DEBUG("times.interval", "false: there is no end_of_duration");
+ return false;
+ }
+
+ // If we've reached here, it means the date does not fall into the current
+ // interval, so we must seek another interval that does match -- unless we
+ // pass by date in so doing, which means we shouldn't alter the current
+ // period of the interval at all.
+
+ date_t scan = *start;
+ date_t end_of_scan = *end_of_duration;
+
+ DEBUG("times.interval", "date = " << date);
+ DEBUG("times.interval", "scan = " << scan);
+ DEBUG("times.interval", "end_of_scan = " << end_of_scan);
+
+ while (date >= scan && (! finish || scan < *finish)) {
+ if (date < end_of_scan) {
+ start = scan;
+ end_of_duration = end_of_scan;
+ next = none;
+
+ DEBUG("times.interval", "true: start = " << *start);
+ DEBUG("times.interval", "true: end_of_duration = " << *end_of_duration);
+
+ return true;
+ }
+
+ scan = duration->add(scan);
+ end_of_scan = duration->add(scan);
+ }
+
+ return false;
+}
+
+date_interval_t& date_interval_t::operator++()
+{
+ if (! start)
+ throw_(date_error, _("Cannot increment an unstarted date interval"));
+
+ stabilize();
+
+ if (! duration)
+ throw_(date_error,
+ _("Cannot increment a date interval without a duration"));
+
+ assert(next);
+
+ if (finish && *next >= *finish) {
+ start = none;
+ } else {
+ start = *next;
+ end_of_duration = duration->add(*start);
+ }
+ next = none;
+
+ resolve_end();
+
+ return *this;
+}
+
+void date_interval_t::dump(std::ostream& out, optional_year current_year)
+{
+ out << _("--- Before stabilization ---") << std::endl;
+
+ if (range)
+ out << _(" range: ") << range->to_string() << std::endl;
+ if (start)
+ out << _(" start: ") << format_date(*start) << std::endl;
+ if (finish)
+ out << _(" finish: ") << format_date(*finish) << std::endl;
+
+ if (duration)
+ out << _("duration: ") << duration->to_string() << std::endl;
+
+ stabilize(begin(current_year));
+
+ out << std::endl
+ << _("--- After stabilization ---") << std::endl;
+
+ if (range)
+ out << _(" range: ") << range->to_string() << std::endl;
+ if (start)
+ out << _(" start: ") << format_date(*start) << std::endl;
+ if (finish)
+ out << _(" finish: ") << format_date(*finish) << std::endl;
+
+ if (duration)
+ out << _("duration: ") << duration->to_string() << std::endl;
+
+ out << std::endl
+ << _("--- Sample dates in range (max. 20) ---") << std::endl;
+
+ date_t last_date;
+
+ for (int i = 0; i < 20 && *this; ++i, ++*this) {
+ out << std::right;
+ out.width(2);
+
+ if (! last_date.is_not_a_date() && last_date == *start)
+ break;
+
+ out << (i + 1) << ": " << format_date(*start);
+ if (duration)
+ out << " -- " << format_date(*inclusive_end());
+ out << std::endl;
+
+ if (! duration)
+ break;
+
+ last_date = *start;
+ }
+}
+
+date_parser_t::lexer_t::token_t date_parser_t::lexer_t::next_token()
+{
+ if (token_cache.kind != token_t::UNKNOWN) {
+ token_t tok = token_cache;
+ token_cache = token_t();
+ return tok;
+ }
+
+ while (begin != end && std::isspace(*begin))
+ begin++;
+
+ if (begin == end)
+ return token_t(token_t::END_REACHED);
+
+ switch (*begin) {
+ case '/': ++begin; return token_t(token_t::TOK_SLASH);
+ case '-': ++begin; return token_t(token_t::TOK_DASH);
+ case '.': ++begin; return token_t(token_t::TOK_DOT);
+ default: break;
+ }
+
+ string::const_iterator start = begin;
+
+ // If the first character is a digit, try parsing the whole argument as a
+ // date using the typical date formats. This allows not only dates like
+ // "2009/08/01", but also dates that fit the user's --input-date-format,
+ // assuming their format fits in one argument and begins with a digit.
+ if (std::isdigit(*begin)) {
+ try {
+ string::const_iterator i = begin;
+ for (i = begin; i != end && ! std::isspace(*i); i++) {}
+ assert(i != begin);
+
+ string possible_date(start, i);
+ date_traits_t traits;
+
+ date_t when = parse_date_mask(possible_date.c_str(), none, &traits);
+ if (! when.is_not_a_date()) {
+ begin = i;
+ return token_t(token_t::TOK_DATE,
+ token_t::content_t(date_specifier_t(when, traits)));
+ }
+ }
+ catch (...) {}
+ }
+
+ start = begin;
+
+ string term;
+ bool alnum = std::isalnum(*begin);
+ for (; (begin != end && ! std::isspace(*begin) &&
+ ((alnum && static_cast<bool>(std::isalnum(*begin))) ||
+ (! alnum && ! static_cast<bool>(std::isalnum(*begin))))); begin++)
+ term.push_back(*begin);
+
+ if (! term.empty()) {
+ if (std::isdigit(term[0])) {
+ if (term.length() == 4)
+ return token_t(token_t::TOK_A_YEAR,
+ token_t::content_t
+ (lexical_cast<date_specifier_t::year_type>(term)));
+ else
+ return token_t(token_t::TOK_INT,
+ token_t::content_t(lexical_cast<unsigned short>(term)));
+ }
+ else if (std::isalpha(term[0])) {
+ to_lower(term);
+
+ if (optional<date_time::months_of_year> month =
+ string_to_month_of_year(term)) {
+ return token_t(token_t::TOK_A_MONTH, token_t::content_t(*month));
+ }
+ else if (optional<date_time::weekdays> wday =
+ string_to_day_of_week(term)) {
+ return token_t(token_t::TOK_A_WDAY, token_t::content_t(*wday));
+ }
+ else if (term == _("from") || term == _("since"))
+ return token_t(token_t::TOK_SINCE);
+ else if (term == _("to") || term == _("until"))
+ return token_t(token_t::TOK_UNTIL);
+ else if (term == _("in"))
+ return token_t(token_t::TOK_IN);
+ else if (term == _("this"))
+ return token_t(token_t::TOK_THIS);
+ else if (term == _("next"))
+ return token_t(token_t::TOK_NEXT);
+ else if (term == _("last"))
+ return token_t(token_t::TOK_LAST);
+ else if (term == _("every"))
+ return token_t(token_t::TOK_EVERY);
+ else if (term == _("today"))
+ return token_t(token_t::TOK_TODAY);
+ else if (term == _("tomorrow"))
+ return token_t(token_t::TOK_TOMORROW);
+ else if (term == _("yesterday"))
+ return token_t(token_t::TOK_YESTERDAY);
+ else if (term == _("year"))
+ return token_t(token_t::TOK_YEAR);
+ else if (term == _("quarter"))
+ return token_t(token_t::TOK_QUARTER);
+ else if (term == _("month"))
+ return token_t(token_t::TOK_MONTH);
+ else if (term == _("week"))
+ return token_t(token_t::TOK_WEEK);
+ else if (term == _("day"))
+ return token_t(token_t::TOK_DAY);
+ else if (term == _("yearly"))
+ return token_t(token_t::TOK_YEARLY);
+ else if (term == _("quarterly"))
+ return token_t(token_t::TOK_QUARTERLY);
+ else if (term == _("bimonthly"))
+ return token_t(token_t::TOK_BIMONTHLY);
+ else if (term == _("monthly"))
+ return token_t(token_t::TOK_MONTHLY);
+ else if (term == _("biweekly"))
+ return token_t(token_t::TOK_BIWEEKLY);
+ else if (term == _("weekly"))
+ return token_t(token_t::TOK_WEEKLY);
+ else if (term == _("daily"))
+ return token_t(token_t::TOK_DAILY);
+ else if (term == _("years"))
+ return token_t(token_t::TOK_YEARS);
+ else if (term == _("quarters"))
+ return token_t(token_t::TOK_QUARTERS);
+ else if (term == _("months"))
+ return token_t(token_t::TOK_MONTHS);
+ else if (term == _("weeks"))
+ return token_t(token_t::TOK_WEEKS);
+ else if (term == _("days"))
+ return token_t(token_t::TOK_DAYS);
+ }
+ else {
+ token_t::expected('\0', term[0]);
+ begin = ++start;
+ }
+ } else {
+ token_t::expected('\0', *begin);
+ }
+
+ return token_t(token_t::UNKNOWN, token_t::content_t(term));
+}
+
+void date_parser_t::lexer_t::token_t::unexpected()
+{
+ switch (kind) {
+ case END_REACHED:
+ kind = UNKNOWN;
+ throw_(date_error, _("Unexpected end of expression"));
+ default: {
+ string desc = to_string();
+ kind = UNKNOWN;
+ throw_(date_error, _("Unexpected date period token '%1'") << desc);
+ }
+ }
+}
+
+void date_parser_t::lexer_t::token_t::expected(char wanted, char c)
+{
+ if (c == '\0' || c == -1) {
+ if (wanted == '\0' || wanted == -1)
+ throw_(date_error, _("Unexpected end"));
+ else
+ throw_(date_error, _("Missing '%1'") << wanted);
+ } else {
+ if (wanted == '\0' || wanted == -1)
+ throw_(date_error, _("Invalid char '%1'") << c);
+ else
+ throw_(date_error, _("Invalid char '%1' (wanted '%2')") << c << wanted);
+ }
+}
+
+namespace {
+ typedef std::map<std::string, datetime_io_t *> datetime_io_map;
+ typedef std::map<std::string, date_io_t *> date_io_map;
+
+ datetime_io_map temp_datetime_io;
+ date_io_map temp_date_io;
+}
+
+std::string format_datetime(const datetime_t& when,
+ const format_type_t format_type,
+ const optional<const char *>& format)
+{
+ if (format_type == FMT_WRITTEN) {
+ return written_datetime_io->format(when);
+ }
+ else if (format_type == FMT_CUSTOM || format) {
+ datetime_io_map::iterator i = temp_datetime_io.find(*format);
+ if (i != temp_datetime_io.end()) {
+ return (*i).second->format(when);
+ } else {
+ datetime_io_t * formatter = new datetime_io_t(*format, false);
+ temp_datetime_io.insert(datetime_io_map::value_type(*format, formatter));
+ return formatter->format(when);
+ }
+ }
+ else if (format_type == FMT_PRINTED) {
+ return printed_datetime_io->format(when);
+ }
+ else {
+ assert(false);
+ return empty_string;
+ }
+}
+
+std::string format_date(const date_t& when,
+ const format_type_t format_type,
+ const optional<const char *>& format)
+{
+ if (format_type == FMT_WRITTEN) {
+ return written_date_io->format(when);
+ }
+ else if (format_type == FMT_CUSTOM || format) {
+ date_io_map::iterator i = temp_date_io.find(*format);
+ if (i != temp_date_io.end()) {
+ return (*i).second->format(when);
+ } else {
+ date_io_t * formatter = new date_io_t(*format, false);
+ temp_date_io.insert(date_io_map::value_type(*format, formatter));
+ return formatter->format(when);
+ }
+ }
+ else if (format_type == FMT_PRINTED) {
+ return printed_date_io->format(when);
+ }
+ else {
+ assert(false);
+ return empty_string;
+ }
+}
+
+namespace {
+ bool is_initialized = false;
+}
+
+void set_datetime_format(const char * format)
+{
+ printed_datetime_io->set_format(format);
+}
+
+void set_date_format(const char * format)
+{
+ printed_date_io->set_format(format);
+}
+
+void set_input_date_format(const char * format)
+{
+ input_date_io.reset(new date_io_t(format, true));
+}
+
+void times_initialize()
+{
+ if (! is_initialized) {
+ input_datetime_io.reset(new datetime_io_t("%Y/%m/%d %H:%M:%S", true));
+
+ written_datetime_io.reset(new datetime_io_t("%Y/%m/%d %H:%M:%S", false));
+ written_date_io.reset(new date_io_t("%Y/%m/%d", false));
+
+ printed_datetime_io.reset(new datetime_io_t("%y-%b-%d %H:%M:%S", false));
+ printed_date_io.reset(new date_io_t("%y-%b-%d", false));
+
+ readers.push_back(shared_ptr<date_io_t>(new date_io_t("%m/%d", true)));
+ readers.push_back(shared_ptr<date_io_t>(new date_io_t("%Y/%m/%d", true)));
+ readers.push_back(shared_ptr<date_io_t>(new date_io_t("%Y/%m", true)));
+ readers.push_back(shared_ptr<date_io_t>(new date_io_t("%y/%m/%d", true)));
+
+ is_initialized = true;
+ }
+}
+
+void times_shutdown()
+{
+ if (is_initialized) {
+ input_datetime_io.reset();
+ input_date_io.reset();
+ written_datetime_io.reset();
+ written_date_io.reset();
+ printed_datetime_io.reset();
+ printed_date_io.reset();
+
+ readers.clear();
+
+ foreach (datetime_io_map::value_type& pair, temp_datetime_io)
+ checked_delete(pair.second);
+ temp_datetime_io.clear();
+
+ foreach (date_io_map::value_type& pair, temp_date_io)
+ checked_delete(pair.second);
+ temp_date_io.clear();
+
+ is_initialized = false;
+ }
+}
+
+void show_period_tokens(std::ostream& out, const string& arg)
+{
+ date_parser_t::lexer_t lexer(arg.begin(), arg.end());
+
+ out << _("--- Period expression tokens ---") << std::endl;
+
+ date_parser_t::lexer_t::token_t token;
+ do {
+ token = lexer.next_token();
+ token.dump(out);
+ out << ": " << token.to_string() << std::endl;
+ }
+ while (token.kind != date_parser_t::lexer_t::token_t::END_REACHED);
+}
+
+} // namespace ledger
diff --git a/src/times.h b/src/times.h
new file mode 100644
index 00000000..826937bb
--- /dev/null
+++ b/src/times.h
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup util
+ */
+
+/**
+ * @file times.h
+ * @author John Wiegley
+ *
+ * @ingroup util
+ *
+ * @brief datetime_t and date_t objects
+ */
+#ifndef _TIMES_H
+#define _TIMES_H
+
+#include "utils.h"
+
+namespace ledger {
+
+DECLARE_EXCEPTION(datetime_error, std::runtime_error);
+DECLARE_EXCEPTION(date_error, std::runtime_error);
+
+typedef boost::posix_time::ptime datetime_t;
+typedef datetime_t::time_duration_type time_duration_t;
+
+inline bool is_valid(const datetime_t& moment) {
+ return ! moment.is_not_a_date_time();
+}
+
+typedef boost::gregorian::date date_t;
+typedef boost::gregorian::date_iterator date_iterator_t;
+
+inline bool is_valid(const date_t& moment) {
+ return ! moment.is_not_a_date();
+}
+
+extern optional<datetime_t> epoch;
+
+#ifdef BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK
+#define TRUE_CURRENT_TIME() (boost::posix_time::microsec_clock::universal_time())
+#define CURRENT_TIME() (epoch ? *epoch : TRUE_CURRENT_TIME())
+#else
+#define TRUE_CURRENT_TIME() (boost::posix_time::second_clock::universal_time())
+#define CURRENT_TIME() (epoch ? *epoch : TRUE_CURRENT_TIME())
+#endif
+#define CURRENT_DATE() \
+ (epoch ? epoch->date() : boost::gregorian::day_clock::universal_day())
+
+extern date_time::weekdays start_of_week;
+
+optional<date_time::weekdays>
+string_to_day_of_week(const std::string& str);
+optional<date_time::months_of_year>
+string_to_month_of_year(const std::string& str);
+
+typedef optional<date_t::year_type> optional_year;
+
+datetime_t parse_datetime(const char * str, optional_year current_year = none);
+
+inline datetime_t parse_datetime(const std::string& str,
+ optional_year current_year = none) {
+ return parse_datetime(str.c_str(), current_year);
+}
+
+date_t parse_date(const char * str, optional_year current_year = none);
+
+inline date_t parse_date(const std::string& str,
+ optional_year current_year = none) {
+ return parse_date(str.c_str(), current_year);
+}
+
+enum format_type_t {
+ FMT_WRITTEN, FMT_PRINTED, FMT_CUSTOM
+};
+
+std::string format_datetime(const datetime_t& when,
+ const format_type_t format_type = FMT_PRINTED,
+ const optional<const char *>& format = none);
+void set_datetime_format(const char * format);
+
+std::string format_date(const date_t& when,
+ const format_type_t format_type = FMT_PRINTED,
+ const optional<const char *>& format = none);
+void set_date_format(const char * format);
+void set_input_date_format(const char * format);
+
+inline void to_xml(std::ostream& out, const datetime_t& when,
+ bool wrap = true)
+{
+ if (wrap) {
+ push_xml x(out, "datetime");
+ out << format_datetime(when, FMT_WRITTEN);
+ } else {
+ out << format_datetime(when, FMT_WRITTEN);
+ }
+}
+
+inline void to_xml(std::ostream& out, const date_t& when,
+ bool wrap = true)
+{
+ if (wrap) {
+ push_xml x(out, "date");
+ out << format_date(when, FMT_WRITTEN);
+ } else {
+ out << format_date(when, FMT_WRITTEN);
+ }
+}
+
+struct date_traits_t
+{
+ bool has_year;
+ bool has_month;
+ bool has_day;
+
+ date_traits_t(bool _has_year = false,
+ bool _has_month = false,
+ bool _has_day = false)
+ : has_year(_has_year), has_month(_has_month), has_day(_has_day) {
+ TRACE_CTOR(date_traits_t, "bool, bool, bool");
+ }
+ date_traits_t(const date_traits_t& traits)
+ : has_year(traits.has_year),
+ has_month(traits.has_month),
+ has_day(traits.has_day) {
+ TRACE_CTOR(date_traits_t, "copy");
+ }
+ ~date_traits_t() throw() {
+ TRACE_DTOR(date_traits_t);
+ }
+
+ date_traits_t& operator=(const date_traits_t& traits) {
+ has_year = traits.has_year;
+ has_month = traits.has_month;
+ has_day = traits.has_day;
+ return *this;
+ }
+
+ bool operator==(const date_traits_t& traits) const {
+ return (has_year == traits.has_year &&
+ has_month == traits.has_month &&
+ has_day == traits.has_day);
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & has_year;
+ ar & has_month;
+ ar & has_day;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+struct date_duration_t
+{
+ enum skip_quantum_t {
+ DAYS, WEEKS, MONTHS, QUARTERS, YEARS
+ } quantum;
+ int length;
+
+ date_duration_t() : quantum(DAYS), length(0) {
+ TRACE_CTOR(date_duration_t, "");
+ }
+ date_duration_t(skip_quantum_t _quantum, int _length)
+ : quantum(_quantum), length(_length) {
+ TRACE_CTOR(date_duration_t, "skip_quantum_t, int");
+ }
+ date_duration_t(const date_duration_t& dur)
+ : quantum(dur.quantum), length(dur.length) {
+ TRACE_CTOR(date_duration_t, "copy");
+ }
+ ~date_duration_t() throw() {
+ TRACE_DTOR(date_duration_t);
+ }
+
+ date_t add(const date_t& date) const {
+ switch (quantum) {
+ case DAYS:
+ return date + gregorian::days(length);
+ case WEEKS:
+ return date + gregorian::weeks(length);
+ case MONTHS:
+ return date + gregorian::months(length);
+ case QUARTERS:
+ return date + gregorian::months(length * 3);
+ case YEARS:
+ return date + gregorian::years(length);
+ default:
+ assert(false); return date_t();
+ }
+ }
+
+ date_t subtract(const date_t& date) const {
+ switch (quantum) {
+ case DAYS:
+ return date - gregorian::days(length);
+ case WEEKS:
+ return date - gregorian::weeks(length);
+ case MONTHS:
+ return date - gregorian::months(length);
+ case QUARTERS:
+ return date - gregorian::months(length * 3);
+ case YEARS:
+ return date - gregorian::years(length);
+ default:
+ assert(false); return date_t();
+ }
+ }
+
+ string to_string() const {
+ std::ostringstream out;
+
+ out << length << ' ';
+
+ switch (quantum) {
+ case DAYS: out << "day"; break;
+ case WEEKS: out << "week"; break;
+ case MONTHS: out << "month"; break;
+ case QUARTERS: out << "quarter"; break;
+ case YEARS: out << "year"; break;
+ default:
+ assert(false);
+ break;
+ }
+
+ if (length > 1)
+ out << 's';
+
+ return out.str();
+ }
+
+ static date_t find_nearest(const date_t& date, skip_quantum_t skip);
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & quantum;
+ ar & length;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class date_specifier_t
+{
+ friend class date_parser_t;
+
+#if 0
+ typedef date_t::year_type year_type;
+#else
+ typedef unsigned short year_type;
+#endif
+ typedef date_t::month_type month_type;
+ typedef date_t::day_type day_type;
+ typedef date_t::day_of_week_type day_of_week_type;
+
+ optional<year_type> year;
+ optional<month_type> month;
+ optional<day_type> day;
+ optional<day_of_week_type> wday;
+
+public:
+ date_specifier_t(const optional<year_type>& _year = none,
+ const optional<month_type>& _month = none,
+ const optional<day_type>& _day = none,
+ const optional<day_of_week_type>& _wday = none)
+ : year(_year), month(_month), day(_day), wday(_wday) {
+ TRACE_CTOR(date_specifier_t,
+ "year_type, month_type, day_type, day_of_week_type");
+ }
+ date_specifier_t(const date_t& date,
+ const optional<date_traits_t>& traits = none) {
+ TRACE_CTOR(date_specifier_t, "date_t, date_traits_t");
+ if (! traits || traits->has_year)
+ year = date.year();
+ if (! traits || traits->has_month)
+ month = date.month();
+ if (! traits || traits->has_day)
+ day = date.day();
+ }
+ date_specifier_t(const date_specifier_t& other)
+ : year(other.year), month(other.month),
+ day(other.day), wday(other.wday) {
+ TRACE_CTOR(date_specifier_t, "copy");
+ }
+ ~date_specifier_t() throw() {
+ TRACE_DTOR(date_specifier_t);
+ }
+
+ date_t begin(const optional_year& current_year = none) const;
+ date_t end(const optional_year& current_year = none) const;
+
+ bool is_within(const date_t& date,
+ const optional_year& current_year = none) const {
+ return date >= begin(current_year) && date < end(current_year);
+ }
+
+ optional<date_duration_t> implied_duration() const {
+ if (day || wday)
+ return date_duration_t(date_duration_t::DAYS, 1);
+ else if (month)
+ return date_duration_t(date_duration_t::MONTHS, 1);
+ else if (year)
+ return date_duration_t(date_duration_t::YEARS, 1);
+ else
+ return none;
+ }
+
+ string to_string() const {
+ std::ostringstream out;
+
+ if (year)
+ out << " year " << *year;
+ if (month)
+ out << " month " << *month;
+ if (day)
+ out << " day " << *day;
+ if (wday)
+ out << " wday " << *wday;
+
+ return out.str();
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & year;
+ ar & month;
+ ar & day;
+ ar & wday;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class date_range_t
+{
+ friend class date_parser_t;
+
+ optional<date_specifier_t> range_begin;
+ optional<date_specifier_t> range_end;
+
+ bool end_inclusive;
+
+public:
+ date_range_t(const optional<date_specifier_t>& _range_begin = none,
+ const optional<date_specifier_t>& _range_end = none)
+ : range_begin(_range_begin), range_end(_range_end),
+ end_inclusive(false) {
+ TRACE_CTOR(date_range_t, "date_specifier_t, date_specifier_t");
+ }
+ date_range_t(const date_range_t& other)
+ : range_begin(other.range_begin), range_end(other.range_end),
+ end_inclusive(other.end_inclusive) {
+ TRACE_CTOR(date_range_t, "date_range_t");
+ }
+ ~date_range_t() throw() {
+ TRACE_DTOR(date_range_t);
+ }
+
+ optional<date_t> begin(const optional_year& current_year = none) const {
+ if (range_begin)
+ return range_begin->begin(current_year);
+ else
+ return none;
+ }
+ optional<date_t> end(const optional_year& current_year = none) const {
+ if (range_end) {
+ if (end_inclusive)
+ return range_end->end(current_year);
+ else
+ return range_end->begin(current_year);
+ } else {
+ return none;
+ }
+ }
+
+ bool is_within(const date_t& date,
+ const optional_year& current_year = none) const {
+ optional<date_t> b = begin(current_year);
+ optional<date_t> e = end(current_year);
+ bool after_begin = b ? date >= *b : true;
+ bool before_end = e ? date < *e : true;
+ return after_begin && before_end;
+ }
+
+ string to_string() const {
+ std::ostringstream out;
+
+ if (range_begin)
+ out << "from" << range_begin->to_string();
+ if (range_end)
+ out << " to" << range_end->to_string();
+
+ return out.str();
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & range_begin;
+ ar & range_end;
+ ar & end_inclusive;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class date_specifier_or_range_t
+{
+ typedef variant<int, date_specifier_t, date_range_t> value_type;
+
+ value_type specifier_or_range;
+
+public:
+ date_specifier_or_range_t() {
+ TRACE_CTOR(date_specifier_or_range_t, "");
+ }
+ date_specifier_or_range_t(const date_specifier_or_range_t& other)
+ : specifier_or_range(other.specifier_or_range) {
+ TRACE_CTOR(date_specifier_or_range_t, "copy");
+ }
+ date_specifier_or_range_t(const date_specifier_t& specifier)
+ : specifier_or_range(specifier) {
+ TRACE_CTOR(date_specifier_or_range_t, "date_specifier_t");
+ }
+ date_specifier_or_range_t(const date_range_t& range)
+ : specifier_or_range(range) {
+ TRACE_CTOR(date_specifier_or_range_t, "date_range_t");
+ }
+ ~date_specifier_or_range_t() throw() {
+ TRACE_DTOR(date_specifier_or_range_t);
+ }
+
+ optional<date_t> begin(const optional_year& current_year = none) const {
+ if (specifier_or_range.type() == typeid(date_specifier_t))
+ return boost::get<date_specifier_t>(specifier_or_range).begin(current_year);
+ else if (specifier_or_range.type() == typeid(date_range_t))
+ return boost::get<date_range_t>(specifier_or_range).begin(current_year);
+ else
+ return none;
+ }
+ optional<date_t> end(const optional_year& current_year = none) const {
+ if (specifier_or_range.type() == typeid(date_specifier_t))
+ return boost::get<date_specifier_t>(specifier_or_range).end(current_year);
+ else if (specifier_or_range.type() == typeid(date_range_t))
+ return boost::get<date_range_t>(specifier_or_range).end(current_year);
+ else
+ return none;
+ }
+
+
+ string to_string() const {
+ std::ostringstream out;
+
+ if (specifier_or_range.type() == typeid(date_specifier_t))
+ out << "in" << boost::get<date_specifier_t>(specifier_or_range).to_string();
+ else if (specifier_or_range.type() == typeid(date_range_t))
+ out << boost::get<date_range_t>(specifier_or_range).to_string();
+
+ return out.str();
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & specifier_or_range;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class date_interval_t : public equality_comparable<date_interval_t>
+{
+public:
+ static date_t add_duration(const date_t& date,
+ const date_duration_t& duration);
+ static date_t subtract_duration(const date_t& date,
+ const date_duration_t& duration);
+
+ optional<date_specifier_or_range_t> range;
+
+ optional<date_t> start; // the real start, after adjustment
+ optional<date_t> finish; // the real end, likewise
+ bool aligned;
+ optional<date_t> next;
+ optional<date_duration_t> duration;
+ optional<date_t> end_of_duration;
+
+ explicit date_interval_t() : aligned(false) {
+ TRACE_CTOR(date_interval_t, "");
+ }
+ date_interval_t(const string& str) : aligned(false) {
+ TRACE_CTOR(date_interval_t, "const string&");
+ parse(str);
+ }
+ date_interval_t(const date_interval_t& other)
+ : range(other.range),
+ start(other.start),
+ finish(other.finish),
+ aligned(other.aligned),
+ next(other.next),
+ duration(other.duration),
+ end_of_duration(other.end_of_duration) {
+ TRACE_CTOR(date_interval_t, "copy");
+ }
+ ~date_interval_t() throw() {
+ TRACE_DTOR(date_interval_t);
+ }
+
+ bool operator==(const date_interval_t& other) const {
+ return (start == other.start &&
+ (! start || *start == *other.start));
+ }
+
+ operator bool() const {
+ return is_valid();
+ }
+
+ optional<date_t> begin(const optional_year& current_year = none) const {
+ return start ? start : (range ? range->begin(current_year) : none);
+ }
+ optional<date_t> end(const optional_year& current_year = none) const {
+ return finish ? finish : (range ? range->end(current_year) : none);
+ }
+
+ void parse(const string& str);
+
+ void resolve_end();
+ void stabilize(const optional<date_t>& date = none);
+
+ bool is_valid() const {
+ return start;
+ }
+
+ /** Find the current or next period containing date. Returns true if the
+ date_interval_t object has been altered to reflect the interval
+ containing date, or false if no such period can be found. */
+ bool find_period(const date_t& date);
+
+ optional<date_t> inclusive_end() const {
+ if (end_of_duration)
+ return *end_of_duration - gregorian::days(1);
+ else
+ return none;
+ }
+
+ date_interval_t& operator++();
+
+ void dump(std::ostream& out, optional_year current_year = none);
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & range;
+ ar & start;
+ ar & finish;
+ ar & aligned;
+ ar & next;
+ ar & duration;
+ ar & end_of_duration;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+void times_initialize();
+void times_shutdown();
+
+void show_period_tokens(std::ostream& out, const string& arg);
+
+std::ostream& operator<<(std::ostream& out, const date_duration_t& duration);
+
+} // namespace ledger
+
+#endif // _TIMES_H
diff --git a/src/token.cc b/src/token.cc
new file mode 100644
index 00000000..81c54a82
--- /dev/null
+++ b/src/token.cc
@@ -0,0 +1,485 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "token.h"
+#include "parser.h"
+
+namespace ledger {
+
+int expr_t::token_t::parse_reserved_word(std::istream& in)
+{
+ char c = static_cast<char>(in.peek());
+
+ if (c == 'a' || c == 'd' || c == 'e' || c == 'f' ||
+ c == 'i' || c == 'o' || c == 'n' || c == 't') {
+ length = 0;
+
+ char buf[6];
+ READ_INTO_(in, buf, 5, c, length, std::isalpha(c));
+
+ switch (buf[0]) {
+ case 'a':
+ if (std::strcmp(buf, "and") == 0) {
+ symbol[0] = '&';
+ symbol[1] = '\0';
+ kind = KW_AND;
+ return 1;
+ }
+ break;
+
+ case 'd':
+ if (std::strcmp(buf, "div") == 0) {
+ symbol[0] = '/';
+ symbol[1] = '/';
+ symbol[2] = '\0';
+ kind = KW_DIV;
+ return 1;
+ }
+ break;
+
+ case 'e':
+ if (std::strcmp(buf, "else") == 0) {
+ symbol[0] = 'L';
+ symbol[1] = 'S';
+ symbol[2] = '\0';
+ kind = KW_ELSE;
+ return 1;
+ }
+ break;
+
+ case 'f':
+ if (std::strcmp(buf, "false") == 0) {
+ kind = VALUE;
+ value = false;
+ return 1;
+ }
+ break;
+
+ case 'i':
+ if (std::strcmp(buf, "if") == 0) {
+ symbol[0] = 'i';
+ symbol[1] = 'f';
+ symbol[2] = '\0';
+ kind = KW_IF;
+ return 1;
+ }
+ break;
+
+ case 'o':
+ if (std::strcmp(buf, "or") == 0) {
+ symbol[0] = '|';
+ symbol[1] = '\0';
+ kind = KW_OR;
+ return 1;
+ }
+ break;
+
+ case 'n':
+ if (std::strcmp(buf, "not") == 0) {
+ symbol[0] = '!';
+ symbol[1] = '\0';
+ kind = EXCLAM;
+ return 1;
+ }
+ break;
+
+ case 't':
+ if (std::strcmp(buf, "true") == 0) {
+ kind = VALUE;
+ value = true;
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+ }
+ return -1;
+}
+
+void expr_t::token_t::parse_ident(std::istream& in)
+{
+ kind = IDENT;
+ length = 0;
+
+ char c, buf[256];
+ READ_INTO_(in, buf, 255, c, length, std::isalnum(c) || c == '_');
+
+ value.set_string(buf);
+}
+
+void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags)
+{
+ if (in.eof()) {
+ kind = TOK_EOF;
+ return;
+ }
+ if (! in.good())
+ throw_(parse_error, _("Input stream no longer valid"));
+
+ char c = peek_next_nonws(in);
+
+ if (in.eof()) {
+ kind = TOK_EOF;
+ return;
+ }
+ if (! in.good())
+ throw_(parse_error, _("Input stream no longer valid"));
+
+ symbol[0] = c;
+ symbol[1] = '\0';
+
+ length = 1;
+
+ switch (c) {
+ case '&':
+ in.get(c);
+ c = static_cast<char>(in.peek());
+ if (c == '&') {
+ in.get(c);
+ kind = KW_AND;
+ length = 2;
+ break;
+ }
+ kind = KW_AND;
+ break;
+ case '|':
+ in.get(c);
+ c = static_cast<char>(in.peek());
+ if (c == '|') {
+ in.get(c);
+ kind = KW_OR;
+ length = 2;
+ break;
+ }
+ kind = KW_OR;
+ break;
+
+ case '(':
+ in.get(c);
+ kind = LPAREN;
+ break;
+ case ')':
+ in.get(c);
+ kind = RPAREN;
+ break;
+
+ case '[': {
+ in.get(c);
+
+ char buf[256];
+ READ_INTO_(in, buf, 255, c, length, c != ']');
+ if (c != ']')
+ expected(']', c);
+
+ in.get(c);
+ length++;
+
+ date_interval_t timespan(buf);
+ optional<date_t> begin = timespan.begin();
+ if (! begin)
+ throw_(parse_error,
+ _("Date specifier does not refer to a starting date"));
+ kind = VALUE;
+ value = *begin;
+ break;
+ }
+
+ case '\'':
+ case '"': {
+ char delim;
+ in.get(delim);
+ char buf[4096];
+ READ_INTO_(in, buf, 4095, c, length, c != delim);
+ if (c != delim)
+ expected(delim, c);
+ in.get(c);
+ length++;
+ kind = VALUE;
+ value.set_string(buf);
+ break;
+ }
+
+ case '{': {
+ in.get(c);
+ amount_t temp;
+ temp.parse(in, PARSE_NO_MIGRATE);
+ in.get(c);
+ if (c != '}')
+ expected('}', c);
+ length++;
+ kind = VALUE;
+ value = temp;
+ break;
+ }
+
+ case '!':
+ in.get(c);
+ c = static_cast<char>(in.peek());
+ if (c == '=') {
+ in.get(c);
+ symbol[1] = c;
+ symbol[2] = '\0';
+ kind = NEQUAL;
+ length = 2;
+ break;
+ }
+ else if (c == '~') {
+ in.get(c);
+ symbol[1] = c;
+ symbol[2] = '\0';
+ kind = NMATCH;
+ length = 2;
+ break;
+ }
+ kind = EXCLAM;
+ break;
+
+ case '-':
+ in.get(c);
+ kind = MINUS;
+ break;
+ case '+':
+ in.get(c);
+ kind = PLUS;
+ break;
+
+ case '*':
+ in.get(c);
+ kind = STAR;
+ break;
+
+ case '?':
+ in.get(c);
+ kind = QUERY;
+ break;
+ case ':':
+ in.get(c);
+ c = static_cast<char>(in.peek());
+ if (c == '=') {
+ in.get(c);
+ symbol[1] = c;
+ symbol[2] = '\0';
+ kind = DEFINE;
+ length = 2;
+ break;
+ }
+ kind = COLON;
+ break;
+
+ case '/': {
+ in.get(c);
+ if (pflags.has_flags(PARSE_OP_CONTEXT)) { // operator context
+ kind = SLASH;
+ } else { // terminal context
+ // Read in the regexp
+ char buf[256];
+ READ_INTO_(in, buf, 255, c, length, c != '/');
+ if (c != '/')
+ expected('/', c);
+ in.get(c);
+ length++;
+
+ kind = VALUE;
+ value.set_mask(buf);
+ }
+ break;
+ }
+
+ case '=':
+ in.get(c);
+ c = static_cast<char>(in.peek());
+ if (c == '~') {
+ in.get(c);
+ symbol[1] = c;
+ symbol[2] = '\0';
+ kind = MATCH;
+ length = 2;
+ break;
+ }
+ else if (c == '=') {
+ in.get(c);
+ symbol[1] = c;
+ symbol[2] = '\0';
+ kind = EQUAL;
+ length = 2;
+ break;
+ }
+ kind = EQUAL;
+ break;
+
+ case '<':
+ in.get(c);
+ if (static_cast<char>(in.peek()) == '=') {
+ in.get(c);
+ symbol[1] = c;
+ symbol[2] = '\0';
+ kind = LESSEQ;
+ length = 2;
+ break;
+ }
+ kind = LESS;
+ break;
+
+ case '>':
+ in.get(c);
+ if (static_cast<char>(in.peek()) == '=') {
+ in.get(c);
+ symbol[1] = c;
+ symbol[2] = '\0';
+ kind = GREATEREQ;
+ length = 2;
+ break;
+ }
+ kind = GREATER;
+ break;
+
+ case '.':
+ in.get(c);
+ kind = DOT;
+ break;
+
+ case ',':
+ in.get(c);
+ kind = COMMA;
+ break;
+
+ case ';':
+ in.get(c);
+ kind = SEMI;
+ break;
+
+ default: {
+ istream_pos_type pos = in.tellg();
+
+ // First, check to see if it's a reserved word, such as: and or not
+ int result = parse_reserved_word(in);
+ if (std::isalpha(c) && result == 1)
+ break;
+
+ // If not, rewind back to the beginning of the word to scan it
+ // again. If the result was -1, it means no identifier was scanned
+ // so we don't have to rewind.
+ if (result == 0) {
+ in.clear();
+ in.seekg(pos, std::ios::beg);
+ if (in.fail())
+ throw_(parse_error, _("Failed to reset input stream"));
+ }
+
+ // When in relaxed parsing mode, we want to migrate commodity flags
+ // so that any precision specified by the user updates the current
+ // maximum displayed precision.
+ parse_flags_t parse_flags;
+
+ if (pflags.has_flags(PARSE_NO_MIGRATE))
+ parse_flags.add_flags(PARSE_NO_MIGRATE);
+ if (pflags.has_flags(PARSE_NO_REDUCE))
+ parse_flags.add_flags(PARSE_NO_REDUCE);
+
+ try {
+ amount_t temp;
+ if (! temp.parse(in, parse_flags.plus_flags(PARSE_SOFT_FAIL))) {
+ // If the amount had no commodity, it must be an unambiguous
+ // variable reference
+
+ in.clear();
+ in.seekg(pos, std::ios::beg);
+ if (in.fail())
+ throw_(parse_error, _("Failed to reset input stream"));
+
+ c = static_cast<char>(in.peek());
+ if (std::isdigit(c) || c == '.')
+ expected('\0', c);
+
+ parse_ident(in);
+ } else {
+ kind = VALUE;
+ value = temp;
+ length = static_cast<std::size_t>(in.tellg() - pos);
+ }
+ }
+ catch (const std::exception& err) {
+ kind = ERROR;
+ length = static_cast<std::size_t>(in.tellg() - pos);
+ throw;
+ }
+ break;
+ }
+ }
+}
+
+void expr_t::token_t::rewind(std::istream& in)
+{
+ in.seekg(- length, std::ios::cur);
+ if (in.fail())
+ throw_(parse_error, _("Failed to rewind input stream"));
+}
+
+
+void expr_t::token_t::unexpected()
+{
+ kind_t prev_kind = kind;
+
+ kind = ERROR;
+
+ switch (prev_kind) {
+ case TOK_EOF:
+ throw_(parse_error, _("Unexpected end of expression"));
+ case IDENT:
+ throw_(parse_error, _("Unexpected symbol '%1'") << value);
+ case VALUE:
+ throw_(parse_error, _("Unexpected value '%1'") << value);
+ default:
+ throw_(parse_error, _("Unexpected token '%1'") << symbol);
+ }
+}
+
+void expr_t::token_t::expected(char wanted, char c)
+{
+ kind = ERROR;
+
+ if (c == '\0' || c == -1) {
+ if (wanted == '\0' || wanted == -1)
+ throw_(parse_error, _("Unexpected end"));
+ else
+ throw_(parse_error, _("Missing '%1'") << wanted);
+ } else {
+ if (wanted == '\0' || wanted == -1)
+ throw_(parse_error, _("Invalid char '%1'") << c);
+ else
+ throw_(parse_error, _("Invalid char '%1' (wanted '%2')") << c << wanted);
+ }
+}
+
+} // namespace ledger
diff --git a/src/token.h b/src/token.h
new file mode 100644
index 00000000..670f16e3
--- /dev/null
+++ b/src/token.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @defgroup expr Value expressions
+ */
+
+/**
+ * @file token.h
+ * @author John Wiegley
+ *
+ * @ingroup expr
+ */
+#ifndef _TOKEN_H
+#define _TOKEN_H
+
+#include "expr.h"
+
+namespace ledger {
+
+struct expr_t::token_t : public noncopyable
+{
+ enum kind_t {
+ ERROR, // an error occurred while tokenizing
+ VALUE, // any kind of literal value
+ IDENT, // [A-Za-z_][-A-Za-z0-9_:]*
+ MASK, // /regexp/
+
+ LPAREN, // (
+ RPAREN, // )
+
+ EQUAL, // ==
+ NEQUAL, // !=
+ LESS, // <
+ LESSEQ, // <=
+ GREATER, // >
+ GREATEREQ, // >=
+
+ DEFINE, // :=
+ ASSIGN, // =
+ MATCH, // =~
+ NMATCH, // !~
+ MINUS, // -
+ PLUS, // +
+ STAR, // *
+ SLASH, // /
+ KW_DIV, // div
+
+ EXCLAM, // !, not
+ KW_AND, // &, &&, and
+ KW_OR, // |, ||, or
+ KW_MOD, // %
+
+ KW_IF, // if
+ KW_ELSE, // else
+
+ QUERY, // ?
+ COLON, // :
+
+ DOT, // .
+ COMMA, // ,
+ SEMI, // ;
+
+ TOK_EOF,
+ UNKNOWN
+
+ } kind;
+
+ char symbol[3];
+ value_t value;
+ std::size_t length;
+
+ explicit token_t() : kind(UNKNOWN), length(0) {
+ TRACE_CTOR(expr_t::token_t, "");
+ }
+ ~token_t() throw() {
+ TRACE_DTOR(expr_t::token_t);
+ }
+
+ token_t& operator=(const token_t& other) {
+ if (&other == this)
+ return *this;
+ assert(false); // only one token object is used at a time
+ return *this;
+ }
+
+ void clear() {
+ kind = UNKNOWN;
+ length = 0;
+ value = NULL_VALUE;
+
+ symbol[0] = '\0';
+ symbol[1] = '\0';
+ symbol[2] = '\0';
+ }
+
+ int parse_reserved_word(std::istream& in);
+ void parse_ident(std::istream& in);
+ void next(std::istream& in, const parse_flags_t& flags);
+ void rewind(std::istream& in);
+ void unexpected();
+ void expected(char wanted, char c = '\0');
+};
+
+} // namespace ledger
+
+#endif // _TOKEN_H
diff --git a/src/unistring.h b/src/unistring.h
new file mode 100644
index 00000000..7c433d9d
--- /dev/null
+++ b/src/unistring.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup utils
+ */
+
+/**
+ * @file unistring.h
+ * @author John Wiegley
+ *
+ * @ingroup utils
+ */
+#ifndef _UNISTRING_H
+#define _UNISTRING_H
+
+namespace ledger {
+
+/**
+ * @class unistring
+ *
+ * @brief Abstract working with UTF-32 encoded Unicode strings
+ *
+ * The input to the string is a UTF8 encoded ledger::string, which can
+ * then have its true length be taken, or characters extracted.
+ */
+class unistring
+{
+public:
+ std::vector<boost::uint32_t> utf32chars;
+
+ unistring() {
+ TRACE_CTOR(unistring, "");
+ }
+ unistring(const std::string& input)
+ {
+ TRACE_CTOR(unistring, "std::string");
+
+ const char * p = input.c_str();
+ std::size_t len = input.length();
+
+ VERIFY(utf8::is_valid(p, p + len));
+ utf8::unchecked::utf8to32(p, p + len, std::back_inserter(utf32chars));
+ }
+ ~unistring() {
+ TRACE_DTOR(unistring);
+ }
+
+ std::size_t length() const {
+ return utf32chars.size();
+ }
+
+ std::string extract(const std::string::size_type begin = 0,
+ const std::string::size_type len = 0) const
+ {
+ std::string utf8result;
+ std::string::size_type this_len = length();
+
+ assert(begin <= this_len);
+ assert(begin + len <= this_len);
+
+ if (this_len)
+ utf8::unchecked::utf32to8
+ (utf32chars.begin() + begin,
+ utf32chars.begin() + begin +
+ (len ? (len > this_len ? this_len : len) : this_len),
+ std::back_inserter(utf8result));
+
+ return utf8result;
+ }
+};
+
+inline void justify(std::ostream& out,
+ const std::string& str,
+ int width,
+ bool right = false,
+ bool redden = false)
+{
+ if (! right) {
+ if (redden) out << "\033[31m";
+ out << str;
+ if (redden) out << "\033[0m";
+ }
+
+ unistring temp(str);
+
+ int spacing = width - int(temp.length());
+ while (spacing-- > 0)
+ out << ' ';
+
+ if (right) {
+ if (redden) out << "\033[31m";
+ out << str;
+ if (redden) out << "\033[0m";
+ }
+}
+
+} // namespace ledger
+
+#endif // _UNISTRING_H
diff --git a/src/utils.cc b/src/utils.cc
new file mode 100644
index 00000000..f2460ba1
--- /dev/null
+++ b/src/utils.cc
@@ -0,0 +1,821 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "times.h"
+
+/**********************************************************************
+ *
+ * Assertions
+ */
+
+#if defined(ASSERTS_ON)
+
+namespace ledger {
+
+DECLARE_EXCEPTION(assertion_failed, std::logic_error);
+
+void debug_assert(const string& reason,
+ const string& func,
+ const string& file,
+ std::size_t line)
+{
+ std::ostringstream buf;
+ buf << "Assertion failed in \"" << file << "\", line " << line
+ << ": " << func << ": " << reason;
+ throw assertion_failed(buf.str());
+}
+
+} // namespace ledger
+
+#endif
+
+/**********************************************************************
+ *
+ * Verification (basically, very slow asserts)
+ */
+
+#if defined(VERIFY_ON)
+
+namespace ledger {
+
+bool verify_enabled = false;
+
+typedef std::pair<std::string, std::size_t> allocation_pair;
+typedef std::map<void *, allocation_pair> memory_map;
+typedef std::multimap<void *, allocation_pair> objects_map;
+
+typedef std::pair<std::size_t, std::size_t> count_size_pair;
+typedef std::map<std::string, count_size_pair> object_count_map;
+
+namespace {
+ bool memory_tracing_active = false;
+
+ memory_map * live_memory = NULL;
+ memory_map * freed_memory = NULL;
+ object_count_map * live_memory_count = NULL;
+ object_count_map * total_memory_count = NULL;
+ objects_map * live_objects = NULL;
+ object_count_map * live_object_count = NULL;
+ object_count_map * total_object_count = NULL;
+ object_count_map * total_ctor_count = NULL;
+}
+
+void initialize_memory_tracing()
+{
+ memory_tracing_active = false;
+
+ live_memory = new memory_map;
+ freed_memory = new memory_map;
+ live_memory_count = new object_count_map;
+ total_memory_count = new object_count_map;
+ live_objects = new objects_map;
+ live_object_count = new object_count_map;
+ total_object_count = new object_count_map;
+ total_ctor_count = new object_count_map;
+
+ memory_tracing_active = true;
+}
+
+void shutdown_memory_tracing()
+{
+ memory_tracing_active = false;
+
+ if (live_objects) {
+ IF_DEBUG("memory.counts")
+ report_memory(std::cerr, true);
+ else IF_DEBUG("memory.counts.live")
+ report_memory(std::cerr);
+ else if (live_objects->size() > 0)
+ report_memory(std::cerr);
+ }
+
+ checked_delete(live_memory); live_memory = NULL;
+ checked_delete(freed_memory); freed_memory = NULL;
+ checked_delete(live_memory_count); live_memory_count = NULL;
+ checked_delete(total_memory_count); total_memory_count = NULL;
+ checked_delete(live_objects); live_objects = NULL;
+ checked_delete(live_object_count); live_object_count = NULL;
+ checked_delete(total_object_count); total_object_count = NULL;
+ checked_delete(total_ctor_count); total_ctor_count = NULL;
+}
+
+inline void add_to_count_map(object_count_map& the_map,
+ const char * name, std::size_t size)
+{
+ object_count_map::iterator k = the_map.find(name);
+ if (k != the_map.end()) {
+ (*k).second.first++;
+ (*k).second.second += size;
+ } else {
+ std::pair<object_count_map::iterator, bool> result =
+ the_map.insert(object_count_map::value_type(name, count_size_pair(1, size)));
+ VERIFY(result.second);
+ }
+}
+
+std::size_t current_memory_size()
+{
+ std::size_t memory_size = 0;
+
+ foreach (const object_count_map::value_type& pair, *live_memory_count)
+ memory_size += pair.second.second;
+
+ return memory_size;
+}
+
+static void trace_new_func(void * ptr, const char * which, std::size_t size)
+{
+ if (! live_memory || ! memory_tracing_active) return;
+
+ memory_tracing_active = false;
+
+ memory_map::iterator i = freed_memory->find(ptr);
+ if (i != freed_memory->end())
+ freed_memory->erase(i);
+
+ live_memory->insert
+ (memory_map::value_type(ptr, allocation_pair(which, size)));
+
+ add_to_count_map(*live_memory_count, which, size);
+ add_to_count_map(*total_memory_count, which, size);
+ add_to_count_map(*total_memory_count, "__ALL__", size);
+
+ memory_tracing_active = true;
+}
+
+static void trace_delete_func(void * ptr, const char * which)
+{
+ if (! live_memory || ! memory_tracing_active) return;
+
+ memory_tracing_active = false;
+
+ // Ignore deletions of memory not tracked, since it's possible that
+ // a user (like boost) allocated a block of memory before memory
+ // tracking began, and then deleted it before memory tracking ended.
+ // If it really is a double-delete, the malloc library on OS/X will
+ // notify me.
+
+ memory_map::iterator i = live_memory->find(ptr);
+ if (i == live_memory->end()) {
+ i = freed_memory->find(ptr);
+ if (i != freed_memory->end())
+ VERIFY(! "Freeing a block of memory twice");
+#if 0
+ // There can be memory allocated by Boost or the standard library, which
+ // was allocated before memory tracing got turned on, that the system
+ // might free for some coincidental reason. As such, we can't rely on
+ // this check being valid. I've seen cases where processes ran to
+ // completion with it on, and then others where valid processes failed.
+ else
+ VERIFY(! "Freeing an unknown block of memory");
+#endif
+ memory_tracing_active = true;
+ return;
+ }
+
+ std::size_t size = (*i).second.second;
+ VERIFY((*i).second.first == which);
+
+ live_memory->erase(i);
+
+ freed_memory->insert
+ (memory_map::value_type(ptr, allocation_pair(which, size)));
+
+ object_count_map::iterator j = live_memory_count->find(which);
+ VERIFY(j != live_memory_count->end());
+
+ (*j).second.second -= size;
+ if (--(*j).second.first == 0)
+ live_memory_count->erase(j);
+
+ memory_tracing_active = true;
+}
+
+} // namespace ledger
+
+void * operator new(std::size_t size) throw (std::bad_alloc) {
+ void * ptr = std::malloc(size);
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_new_func(ptr, "new", size);
+ return ptr;
+}
+void * operator new(std::size_t size, const std::nothrow_t&) throw() {
+ void * ptr = std::malloc(size);
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_new_func(ptr, "new", size);
+ return ptr;
+}
+void * operator new[](std::size_t size) throw (std::bad_alloc) {
+ void * ptr = std::malloc(size);
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_new_func(ptr, "new[]", size);
+ return ptr;
+}
+void * operator new[](std::size_t size, const std::nothrow_t&) throw() {
+ void * ptr = std::malloc(size);
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_new_func(ptr, "new[]", size);
+ return ptr;
+}
+void operator delete(void * ptr) throw() {
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_delete_func(ptr, "new");
+ std::free(ptr);
+}
+void operator delete(void * ptr, const std::nothrow_t&) throw() {
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_delete_func(ptr, "new");
+ std::free(ptr);
+}
+void operator delete[](void * ptr) throw() {
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_delete_func(ptr, "new[]");
+ std::free(ptr);
+}
+void operator delete[](void * ptr, const std::nothrow_t&) throw() {
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_delete_func(ptr, "new[]");
+ std::free(ptr);
+}
+
+namespace ledger {
+
+inline void report_count_map(std::ostream& out, object_count_map& the_map)
+{
+ foreach (object_count_map::value_type& pair, the_map)
+ out << " " << std::right << std::setw(12) << pair.second.first
+ << " " << std::right << std::setw(7) << pair.second.second
+ << " " << std::left << pair.first
+ << std::endl;
+}
+
+std::size_t current_objects_size()
+{
+ std::size_t objects_size = 0;
+
+ foreach (const object_count_map::value_type& pair, *live_object_count)
+ objects_size += pair.second.second;
+
+ return objects_size;
+}
+
+void trace_ctor_func(void * ptr, const char * cls_name, const char * args,
+ std::size_t cls_size)
+{
+ if (! live_objects || ! memory_tracing_active) return;
+
+ memory_tracing_active = false;
+
+ static char name[1024];
+ std::strcpy(name, cls_name);
+ std::strcat(name, "(");
+ std::strcat(name, args);
+ std::strcat(name, ")");
+
+ DEBUG("memory.debug", "TRACE_CTOR " << ptr << " " << name);
+
+ live_objects->insert
+ (objects_map::value_type(ptr, allocation_pair(cls_name, cls_size)));
+
+ add_to_count_map(*live_object_count, cls_name, cls_size);
+ add_to_count_map(*total_object_count, cls_name, cls_size);
+ add_to_count_map(*total_object_count, "__ALL__", cls_size);
+ add_to_count_map(*total_ctor_count, name, cls_size);
+
+ memory_tracing_active = true;
+}
+
+void trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size)
+{
+ if (! live_objects || ! memory_tracing_active) return;
+
+ memory_tracing_active = false;
+
+ DEBUG("memory.debug", "TRACE_DTOR " << ptr << " " << cls_name);
+
+ objects_map::iterator i = live_objects->find(ptr);
+ if (i == live_objects->end()) {
+ warning_(_("Attempting to delete %1 a non-living %2") << ptr << cls_name);
+ memory_tracing_active = true;
+ return;
+ }
+
+ std::size_t ptr_count = live_objects->count(ptr);
+ for (std::size_t x = 0; x < ptr_count; x++, i++) {
+ if ((*i).second.first == cls_name) {
+ live_objects->erase(i);
+ break;
+ }
+ }
+
+ object_count_map::iterator k = live_object_count->find(cls_name);
+ if (k == live_object_count->end()) {
+ warning_(_("Failed to find %1 in live object counts") << cls_name);
+ memory_tracing_active = true;
+ return;
+ }
+
+ (*k).second.second -= cls_size;
+ if (--(*k).second.first == 0)
+ live_object_count->erase(k);
+
+ memory_tracing_active = true;
+}
+
+void report_memory(std::ostream& out, bool report_all)
+{
+ if (! live_memory || ! memory_tracing_active) return;
+
+ if (live_memory_count->size() > 0) {
+ out << "NOTE: There may be memory held by Boost "
+ << "and libstdc++ after ledger::shutdown()" << std::endl;
+ out << "Live memory count:" << std::endl;
+ report_count_map(out, *live_memory_count);
+ }
+
+ if (live_memory->size() > 0) {
+ out << "Live memory:" << std::endl;
+
+ foreach (const memory_map::value_type& pair, *live_memory)
+ out << " " << std::right << std::setw(12) << pair.first
+ << " " << std::right << std::setw(7) << pair.second.second
+ << " " << std::left << pair.second.first
+ << std::endl;
+ }
+
+ if (report_all && total_memory_count->size() > 0) {
+ out << "Total memory counts:" << std::endl;
+ report_count_map(out, *total_memory_count);
+ }
+
+ if (live_object_count->size() > 0) {
+ out << "Live object count:" << std::endl;
+ report_count_map(out, *live_object_count);
+ }
+
+ if (live_objects->size() > 0) {
+ out << "Live objects:" << std::endl;
+
+ foreach (const objects_map::value_type& pair, *live_objects)
+ out << " " << std::right << std::setw(12) << pair.first
+ << " " << std::right << std::setw(7) << pair.second.second
+ << " " << std::left << pair.second.first
+ << std::endl;
+ }
+
+ if (report_all) {
+ if (total_object_count->size() > 0) {
+ out << "Total object counts:" << std::endl;
+ report_count_map(out, *total_object_count);
+ }
+
+ if (total_ctor_count->size() > 0) {
+ out << "Total constructor counts:" << std::endl;
+ report_count_map(out, *total_ctor_count);
+ }
+ }
+}
+
+} // namespace ledger
+
+#endif // VERIFY_ON
+
+/**********************************************************************
+ *
+ * String wrapper
+ */
+
+namespace ledger {
+
+#if defined(VERIFY_ON) || defined(HAVE_BOOST_PYTHON)
+
+string::string() : std::string() {
+ TRACE_CTOR(string, "");
+}
+string::string(const string& str) : std::string(str) {
+ TRACE_CTOR(string, "copy");
+}
+string::string(const std::string& str) : std::string(str) {
+ TRACE_CTOR(string, "const std::string&");
+}
+string::string(size_type len, char x) : std::string(len, x) {
+ TRACE_CTOR(string, "size_type, char");
+}
+string::string(const char * str) : std::string(str) {
+ TRACE_CTOR(string, "const char *");
+}
+string::string(const char * str, const char * end) : std::string(str, end) {
+ TRACE_CTOR(string, "const char *, const char *");
+}
+string::string(const string& str, size_type x) : std::string(str, x) {
+ TRACE_CTOR(string, "const string&, size_type");
+}
+string::string(const string& str, size_type x, size_type y)
+ : std::string(str, x, y) {
+ TRACE_CTOR(string, "const string&, size_type, size_type");
+}
+string::string(const char * str, size_type x) : std::string(str, x) {
+ TRACE_CTOR(string, "const char *, size_type");
+}
+string::string(const char * str, size_type x, size_type y)
+ : std::string(str, x, y) {
+ TRACE_CTOR(string, "const char *, size_type, size_type");
+}
+string::~string() throw() {
+ TRACE_DTOR(string);
+}
+
+#endif // defined(VERIFY_ON) || defined(HAVE_BOOST_PYTHON)
+
+string empty_string("");
+
+strings_list split_arguments(const char * line)
+{
+ strings_list args;
+
+ char buf[4096];
+ char * q = buf;
+ char in_quoted_string = '\0';
+
+ for (const char * p = line; *p; p++) {
+ if (! in_quoted_string && std::isspace(*p)) {
+ if (q != buf) {
+ *q = '\0';
+ args.push_back(buf);
+ q = buf;
+ }
+ }
+ else if (in_quoted_string != '\'' && *p == '\\') {
+ p++;
+ if (! *p)
+ throw_(std::logic_error, _("Invalid use of backslash"));
+ *q++ = *p;
+ }
+ else if (in_quoted_string != '"' && *p == '\'') {
+ if (in_quoted_string == '\'')
+ in_quoted_string = '\0';
+ else
+ in_quoted_string = '\'';
+ }
+ else if (in_quoted_string != '\'' && *p == '"') {
+ if (in_quoted_string == '"')
+ in_quoted_string = '\0';
+ else
+ in_quoted_string = '"';
+ }
+ else {
+ *q++ = *p;
+ }
+ }
+
+ if (in_quoted_string)
+ throw_(std::logic_error,
+ _("Unterminated string, expected '%1'") << in_quoted_string);
+
+ if (q != buf) {
+ *q = '\0';
+ args.push_back(buf);
+ }
+
+ return args;
+}
+
+} // namespace ledger
+
+/**********************************************************************
+ *
+ * Logging
+ */
+
+#if defined(LOGGING_ON)
+
+namespace ledger {
+
+log_level_t _log_level = LOG_WARN;
+std::ostream * _log_stream = &std::cerr;
+std::ostringstream _log_buffer;
+
+#if defined(TRACING_ON)
+uint8_t _trace_level;
+#endif
+
+static inline void stream_memory_size(std::ostream& out, std::size_t size)
+{
+ if (size < 1024)
+ out << size << 'b';
+ else if (size < (1024 * 1024))
+ out << (double(size) / 1024.0) << 'K';
+ else if (size < (1024 * 1024 * 1024))
+ out << (double(size) / (1024.0 * 1024.0)) << 'M';
+ else
+ out << (double(size) / (1024.0 * 1024.0 * 1024.0)) << 'G';
+}
+
+static bool logger_has_run = false;
+static ptime logger_start;
+
+bool logger_func(log_level_t level)
+{
+ if (! logger_has_run) {
+ logger_has_run = true;
+ logger_start = TRUE_CURRENT_TIME();
+
+#if defined(VERIFY_ON)
+ IF_VERIFY()
+ *_log_stream << " TIME OBJSZ MEMSZ" << std::endl;
+#else
+ IF_VERIFY()
+ *_log_stream << " TIME" << std::endl;
+#endif
+ }
+
+ *_log_stream << std::right << std::setw(5)
+ << (TRUE_CURRENT_TIME() -
+ logger_start).total_milliseconds() << "ms";
+
+#if defined(VERIFY_ON)
+ IF_VERIFY() {
+ *_log_stream << std::right << std::setw(6) << std::setprecision(3);
+ stream_memory_size(*_log_stream, current_objects_size());
+ *_log_stream << std::right << std::setw(6) << std::setprecision(3);
+ stream_memory_size(*_log_stream, current_memory_size());
+ }
+#endif
+
+ *_log_stream << " " << std::left << std::setw(7);
+
+ switch (level) {
+ case LOG_CRIT: *_log_stream << "[CRIT]"; break;
+ case LOG_FATAL: *_log_stream << "[FATAL]"; break;
+ case LOG_ASSERT: *_log_stream << "[ASSRT]"; break;
+ case LOG_ERROR: *_log_stream << "[ERROR]"; break;
+ case LOG_VERIFY: *_log_stream << "[VERFY]"; break;
+ case LOG_WARN: *_log_stream << "[WARN]"; break;
+ case LOG_INFO: *_log_stream << "[INFO]"; break;
+ case LOG_EXCEPT: *_log_stream << "[EXCPT]"; break;
+ case LOG_DEBUG: *_log_stream << "[DEBUG]"; break;
+ case LOG_TRACE: *_log_stream << "[TRACE]"; break;
+
+ case LOG_OFF:
+ case LOG_ALL:
+ assert(false);
+ break;
+ }
+
+ *_log_stream << ' ' << _log_buffer.str() << std::endl;
+ _log_buffer.str("");
+
+ return true;
+}
+
+} // namespace ledger
+
+#if defined(DEBUG_ON)
+
+namespace ledger {
+
+optional<std::string> _log_category;
+
+struct __maybe_enable_debugging {
+ __maybe_enable_debugging() {
+ const char * p = std::getenv("LEDGER_DEBUG");
+ if (p != NULL) {
+ _log_level = LOG_DEBUG;
+ _log_category = p;
+ }
+ }
+} __maybe_enable_debugging_obj;
+
+} // namespace ledger
+
+#endif // DEBUG_ON
+#endif // LOGGING_ON
+
+/**********************************************************************
+ *
+ * Timers (allows log xacts to specify cumulative time spent)
+ */
+
+#if defined(LOGGING_ON) && defined(TIMERS_ON)
+
+namespace ledger {
+
+struct timer_t
+{
+ log_level_t level;
+ ptime begin;
+ time_duration spent;
+ std::string description;
+ bool active;
+
+ timer_t(log_level_t _level, std::string _description)
+ : level(_level), begin(TRUE_CURRENT_TIME()),
+ spent(time_duration(0, 0, 0, 0)),
+ description(_description), active(true) {}
+};
+
+typedef std::map<std::string, timer_t> timer_map;
+
+static timer_map timers;
+
+void start_timer(const char * name, log_level_t lvl)
+{
+#if defined(VERIFY_ON)
+ bool tracing_active = memory_tracing_active;
+ memory_tracing_active = false;
+#endif
+
+ timer_map::iterator i = timers.find(name);
+ if (i == timers.end()) {
+ timers.insert(timer_map::value_type(name, timer_t(lvl, _log_buffer.str())));
+ } else {
+ assert((*i).second.description == _log_buffer.str());
+ (*i).second.begin = TRUE_CURRENT_TIME();
+ (*i).second.active = true;
+ }
+ _log_buffer.str("");
+
+#if defined(VERIFY_ON)
+ memory_tracing_active = tracing_active;
+#endif
+}
+
+void stop_timer(const char * name)
+{
+#if defined(VERIFY_ON)
+ bool tracing_active = memory_tracing_active;
+ memory_tracing_active = false;
+#endif
+
+ timer_map::iterator i = timers.find(name);
+ assert(i != timers.end());
+
+ (*i).second.spent += TRUE_CURRENT_TIME() - (*i).second.begin;
+ (*i).second.active = false;
+
+#if defined(VERIFY_ON)
+ memory_tracing_active = tracing_active;
+#endif
+}
+
+void finish_timer(const char * name)
+{
+#if defined(VERIFY_ON)
+ bool tracing_active = memory_tracing_active;
+ memory_tracing_active = false;
+#endif
+
+ timer_map::iterator i = timers.find(name);
+ if (i == timers.end()) {
+#if defined(VERIFY_ON)
+ memory_tracing_active = tracing_active;
+#endif
+ return;
+ }
+
+ time_duration spent = (*i).second.spent;
+ if ((*i).second.active) {
+ spent = TRUE_CURRENT_TIME() - (*i).second.begin;
+ (*i).second.active = false;
+ }
+
+ _log_buffer << (*i).second.description << ' ';
+
+ bool need_paren =
+ (*i).second.description[(*i).second.description.size() - 1] != ':';
+
+ if (need_paren)
+ _log_buffer << '(';
+
+ _log_buffer << spent.total_milliseconds() << "ms";
+
+ if (need_paren)
+ _log_buffer << ')';
+
+ logger_func((*i).second.level);
+
+ timers.erase(i);
+
+#if defined(VERIFY_ON)
+ memory_tracing_active = tracing_active;
+#endif
+}
+
+} // namespace ledger
+
+#endif // LOGGING_ON && TIMERS_ON
+
+/**********************************************************************
+ *
+ * Signal handlers
+ */
+
+caught_signal_t caught_signal = NONE_CAUGHT;
+
+void sigint_handler(int)
+{
+ caught_signal = INTERRUPTED;
+}
+
+void sigpipe_handler(int)
+{
+ caught_signal = PIPE_CLOSED;
+}
+
+/**********************************************************************
+ *
+ * General utility functions
+ */
+
+namespace ledger {
+
+const string version = PACKAGE_VERSION;
+
+path expand_path(const path& pathname)
+{
+ if (pathname.empty())
+ return pathname;
+
+ std::string path_string = pathname.string();
+ const char * pfx = NULL;
+ string::size_type pos = path_string.find_first_of('/');
+
+ if (path_string.length() == 1 || pos == 1) {
+ pfx = std::getenv("HOME");
+#ifdef HAVE_GETPWUID
+ if (! pfx) {
+ // Punt. We're trying to expand ~/, but HOME isn't set
+ struct passwd * pw = getpwuid(getuid());
+ if (pw)
+ pfx = pw->pw_dir;
+ }
+#endif
+ }
+#ifdef HAVE_GETPWNAM
+ else {
+ string user(path_string, 1, pos == string::npos ?
+ string::npos : pos - 1);
+ struct passwd * pw = getpwnam(user.c_str());
+ if (pw)
+ pfx = pw->pw_dir;
+ }
+#endif
+
+ // if we failed to find an expansion, return the path unchanged.
+
+ if (! pfx)
+ return pathname;
+
+ string result(pfx);
+
+ if (pos == string::npos)
+ return result;
+
+ if (result.length() == 0 || result[result.length() - 1] != '/')
+ result += '/';
+
+ result += path_string.substr(pos + 1);
+
+ return result;
+}
+
+path resolve_path(const path& pathname)
+{
+ path temp = pathname;
+ if (temp.string()[0] == '~')
+ temp = expand_path(temp);
+ temp.normalize();
+ return temp;
+}
+
+} // namespace ledger
diff --git a/src/utils.h b/src/utils.h
new file mode 100644
index 00000000..ab8fb495
--- /dev/null
+++ b/src/utils.h
@@ -0,0 +1,713 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @defgroup util General utilities
+ */
+
+/**
+ * @file utils.h
+ * @author John Wiegley
+ *
+ * @ingroup util
+ *
+ * @brief General utility facilities used by Ledger
+ */
+#ifndef _UTILS_H
+#define _UTILS_H
+
+/**
+ * @name Default values
+ */
+/*@{*/
+
+#if defined(DEBUG_MODE)
+#define VERIFY_ON 1
+#define TRACING_ON 1
+#define DEBUG_ON 1
+#define TIMERS_ON 1
+#elif defined(NDEBUG)
+#define NO_ASSERTS 1
+#define NO_LOGGING 1
+#else
+#define TRACING_ON 1 // use --trace X to enable
+#define TIMERS_ON 1
+#endif
+
+/*@}*/
+
+/**
+ * @name Forward declarations
+ */
+/*@{*/
+
+namespace ledger {
+ using namespace boost;
+
+#if defined(VERIFY_ON) || defined(HAVE_BOOST_PYTHON)
+ class string;
+#else
+ typedef std::string string;
+#endif
+
+ typedef std::list<string> strings_list;
+
+ typedef posix_time::ptime ptime;
+ typedef ptime::time_duration_type time_duration;
+ typedef gregorian::date date;
+ typedef gregorian::date_duration date_duration;
+ typedef posix_time::seconds seconds;
+
+ typedef boost::filesystem::path path;
+ typedef boost::filesystem::ifstream ifstream;
+ typedef boost::filesystem::ofstream ofstream;
+ typedef boost::filesystem::filesystem_error filesystem_error;
+}
+
+/*@}*/
+
+/**
+ * @name Assertions
+ */
+/*@{*/
+
+#ifdef assert
+#undef assert
+#endif
+
+#if ! defined(NO_ASSERTS)
+#define ASSERTS_ON 1
+#endif
+#if defined(ASSERTS_ON)
+
+namespace ledger {
+ void debug_assert(const string& reason, const string& func,
+ const string& file, std::size_t line);
+}
+
+#define assert(x) \
+ ((x) ? ((void)0) : debug_assert(#x, BOOST_CURRENT_FUNCTION, \
+ __FILE__, __LINE__))
+
+#else // ! ASSERTS_ON
+
+#define assert(x)
+
+#endif // ASSERTS_ON
+
+/*@}*/
+
+/**
+ * @name Verification (i.e., heavy asserts)
+ */
+/*@{*/
+
+#if defined(VERIFY_ON)
+
+namespace ledger {
+
+extern bool verify_enabled;
+
+#define VERIFY(x) (ledger::verify_enabled ? assert(x) : ((void)0))
+#define DO_VERIFY() ledger::verify_enabled
+
+void initialize_memory_tracing();
+void shutdown_memory_tracing();
+
+std::size_t current_memory_size();
+std::size_t current_objects_size();
+
+void trace_ctor_func(void * ptr, const char * cls_name, const char * args,
+ std::size_t cls_size);
+void trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size);
+
+#define TRACE_CTOR(cls, args) \
+ (DO_VERIFY() ? \
+ ledger::trace_ctor_func(this, #cls, args, sizeof(cls)) : ((void)0))
+#define TRACE_DTOR(cls) \
+ (DO_VERIFY() ? \
+ ledger::trace_dtor_func(this, #cls, sizeof(cls)) : ((void)0))
+
+void report_memory(std::ostream& out, bool report_all = false);
+
+} // namespace ledger
+
+#else // ! VERIFY_ON
+
+#define VERIFY(x)
+#define DO_VERIFY() true
+#define TRACE_CTOR(cls, args)
+#define TRACE_DTOR(cls)
+
+#endif // VERIFY_ON
+
+#define IF_VERIFY() if (DO_VERIFY())
+
+/*@}*/
+
+/**
+ * @name String wrapper
+ *
+ * This string type is a wrapper around std::string that allows us to trace
+ * constructor and destructor calls. It also makes ledger's use of strings a
+ * unique type, that the Boost.Python code can use as the basis for
+ * transparent Unicode conversions.
+ */
+/*@{*/
+
+namespace ledger {
+
+#if defined(VERIFY_ON) || defined(HAVE_BOOST_PYTHON)
+
+class string : public std::string
+{
+public:
+ string();
+ string(const string& str);
+ string(const std::string& str);
+ string(size_type len, char x);
+ template<class _InputIterator>
+ string(_InputIterator __beg, _InputIterator __end)
+ : std::string(__beg, __end) {
+ TRACE_CTOR(string, "InputIterator, InputIterator");
+ }
+ string(const char * str);
+ string(const char * str, const char * end);
+ string(const string& str, size_type x);
+ string(const string& str, size_type x, size_type y);
+ string(const char * str, size_type x);
+ string(const char * str, size_type x, size_type y);
+ ~string() throw();
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<std::string>(*this);
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+inline string operator+(const string& __lhs, const string& __rhs)
+{
+ string __str(__lhs);
+ __str.append(__rhs);
+ return __str;
+}
+
+string operator+(const char* __lhs, const string& __rhs);
+string operator+(char __lhs, const string& __rhs);
+
+inline string operator+(const string& __lhs, const char* __rhs)
+{
+ string __str(__lhs);
+ __str.append(__rhs);
+ return __str;
+}
+
+inline string operator+(const string& __lhs, char __rhs)
+{
+ typedef string __string_type;
+ typedef string::size_type __size_type;
+ __string_type __str(__lhs);
+ __str.append(__size_type(1), __rhs);
+ return __str;
+}
+
+inline bool operator==(const string& __lhs, const string& __rhs)
+{ return __lhs.compare(__rhs) == 0; }
+
+inline bool operator==(const char* __lhs, const string& __rhs)
+{ return __rhs.compare(__lhs) == 0; }
+
+inline bool operator==(const string& __lhs, const char* __rhs)
+{ return __lhs.compare(__rhs) == 0; }
+
+inline bool operator!=(const string& __lhs, const string& __rhs)
+{ return __rhs.compare(__lhs) != 0; }
+
+inline bool operator!=(const char* __lhs, const string& __rhs)
+{ return __rhs.compare(__lhs) != 0; }
+
+inline bool operator!=(const string& __lhs, const char* __rhs)
+{ return __lhs.compare(__rhs) != 0; }
+
+#endif // defined(VERIFY_ON) || defined(HAVE_BOOST_PYTHON)
+
+extern string empty_string;
+
+strings_list split_arguments(const char * line);
+
+} // namespace ledger
+
+/*@}*/
+
+/**
+ * @name Tracing and logging
+ */
+/*@{*/
+
+#if ! defined(NO_LOGGING)
+#define LOGGING_ON 1
+#endif
+#if defined(LOGGING_ON)
+
+namespace ledger {
+
+enum log_level_t {
+ LOG_OFF = 0,
+ LOG_CRIT,
+ LOG_FATAL,
+ LOG_ASSERT,
+ LOG_ERROR,
+ LOG_VERIFY,
+ LOG_WARN,
+ LOG_INFO,
+ LOG_EXCEPT,
+ LOG_DEBUG,
+ LOG_TRACE,
+ LOG_ALL
+};
+
+extern log_level_t _log_level;
+extern std::ostream * _log_stream;
+extern std::ostringstream _log_buffer;
+
+bool logger_func(log_level_t level);
+
+#define LOGGER(cat) \
+ static const char * const _this_category = cat
+
+#if defined(TRACING_ON)
+
+extern uint8_t _trace_level;
+
+#define SHOW_TRACE(lvl) \
+ (ledger::_log_level >= ledger::LOG_TRACE && lvl <= ledger::_trace_level)
+#define TRACE(lvl, msg) \
+ (SHOW_TRACE(lvl) ? \
+ ((ledger::_log_buffer << msg), \
+ ledger::logger_func(ledger::LOG_TRACE)) : false)
+
+#else // TRACING_ON
+
+#define SHOW_TRACE(lvl) false
+#define TRACE(lvl, msg)
+
+#endif // TRACING_ON
+
+#if defined(DEBUG_ON)
+
+extern optional<std::string> _log_category;
+
+inline bool category_matches(const char * cat) {
+ return _log_category && starts_with(cat, *_log_category);
+}
+
+#define SHOW_DEBUG(cat) \
+ (ledger::_log_level >= ledger::LOG_DEBUG && ledger::category_matches(cat))
+#define SHOW_DEBUG_() SHOW_DEBUG(_this_category)
+
+#define DEBUG(cat, msg) \
+ (SHOW_DEBUG(cat) ? \
+ ((ledger::_log_buffer << msg), \
+ ledger::logger_func(ledger::LOG_DEBUG)) : false)
+#define DEBUG_(msg) DEBUG(_this_category, msg)
+
+#else // DEBUG_ON
+
+#define SHOW_DEBUG(cat) false
+#define SHOW_DEBUG_() false
+#define DEBUG(cat, msg)
+#define DEBUG_(msg)
+
+#endif // DEBUG_ON
+
+#define LOG_MACRO(level, msg) \
+ (ledger::_log_level >= level ? \
+ ((ledger::_log_buffer << msg), ledger::logger_func(level)) : false)
+
+#define SHOW_INFO() (ledger::_log_level >= ledger::LOG_INFO)
+#define SHOW_WARN() (ledger::_log_level >= ledger::LOG_WARN)
+#define SHOW_ERROR() (ledger::_log_level >= ledger::LOG_ERROR)
+#define SHOW_FATAL() (ledger::_log_level >= ledger::LOG_FATAL)
+#define SHOW_CRITICAL() (ledger::_log_level >= ledger::LOG_CRIT)
+
+#define INFO(msg) LOG_MACRO(ledger::LOG_INFO, msg)
+#define WARN(msg) LOG_MACRO(ledger::LOG_WARN, msg)
+#define ERROR(msg) LOG_MACRO(ledger::LOG_ERROR, msg)
+#define FATAL(msg) LOG_MACRO(ledger::LOG_FATAL, msg)
+#define CRITICAL(msg) LOG_MACRO(ledger::LOG_CRIT, msg)
+#define EXCEPTION(msg) LOG_MACRO(ledger::LOG_EXCEPT, msg)
+
+} // namespace ledger
+
+#else // ! LOGGING_ON
+
+#define LOGGER(cat)
+
+#define SHOW_TRACE(lvl) false
+#define SHOW_DEBUG(cat) false
+#define SHOW_DEBUG_() false
+#define SHOW_INFO() false
+#define SHOW_WARN() false
+#define SHOW_ERROR() false
+#define SHOW_FATAL() false
+#define SHOW_CRITICAL() false
+
+#define TRACE(lvl, msg)
+#define DEBUG(cat, msg)
+#define DEBUG_(msg)
+#define INFO(msg)
+#define WARN(msg)
+#define ERROR(msg)
+#define FATAL(msg)
+#define CRITICAL(msg)
+
+#endif // LOGGING_ON
+
+#define IF_TRACE(lvl) if (SHOW_TRACE(lvl))
+#define IF_DEBUG(cat) if (SHOW_DEBUG(cat))
+#define IF_DEBUG_() if (SHOW_DEBUG_())
+#define IF_INFO() if (SHOW_INFO())
+#define IF_WARN() if (SHOW_WARN())
+#define IF_ERROR() if (SHOW_ERROR())
+#define IF_FATAL() if (SHOW_FATAL())
+#define IF_CRITICAL() if (SHOW_CRITICAL())
+
+/*@}*/
+
+/**
+ * @name Timers
+ * This allows log xacts to specify cumulative time spent.
+ */
+/*@{*/
+
+#if defined(LOGGING_ON) && defined(TIMERS_ON)
+
+namespace ledger {
+
+void start_timer(const char * name, log_level_t lvl);
+void stop_timer(const char * name);
+void finish_timer(const char * name);
+
+#if defined(TRACING_ON)
+#define TRACE_START(name, lvl, msg) \
+ (SHOW_TRACE(lvl) ? \
+ ((ledger::_log_buffer << msg), \
+ ledger::start_timer(#name, ledger::LOG_TRACE)) : ((void)0))
+#define TRACE_STOP(name, lvl) \
+ (SHOW_TRACE(lvl) ? ledger::stop_timer(#name) : ((void)0))
+#define TRACE_FINISH(name, lvl) \
+ (SHOW_TRACE(lvl) ? ledger::finish_timer(#name) : ((void)0))
+#else
+#define TRACE_START(name, lvl, msg)
+#define TRACE_STOP(name)
+#define TRACE_FINISH(name)
+#endif
+
+#if defined(DEBUG_ON)
+#define DEBUG_START(name, cat, msg) \
+ (SHOW_DEBUG(cat) ? \
+ ((ledger::_log_buffer << msg), \
+ ledger::start_timer(#name, ledger::LOG_DEBUG)) : ((void)0))
+#define DEBUG_START_(name, msg) \
+ DEBUG_START_(name, _this_category, msg)
+#define DEBUG_STOP(name, cat) \
+ (SHOW_DEBUG(cat) ? ledger::stop_timer(#name) : ((void)0))
+#define DEBUG_STOP_(name) \
+ DEBUG_STOP_(name, _this_category)
+#define DEBUG_FINISH(name, cat) \
+ (SHOW_DEBUG(cat) ? ledger::finish_timer(#name) : ((void)0))
+#define DEBUG_FINISH_(name) \
+ DEBUG_FINISH_(name, _this_category)
+#else
+#define DEBUG_START(name, cat, msg)
+#define DEBUG_START_(name, msg)
+#define DEBUG_STOP(name)
+#define DEBUG_FINISH(name)
+#endif
+
+#define INFO_START(name, msg) \
+ (SHOW_INFO() ? \
+ ((ledger::_log_buffer << msg), \
+ ledger::start_timer(#name, ledger::LOG_INFO)) : ((void)0))
+#define INFO_STOP(name) \
+ (SHOW_INFO() ? stop_timer(#name) : ((void)0))
+#define INFO_FINISH(name) \
+ (SHOW_INFO() ? finish_timer(#name) : ((void)0))
+
+} // namespace ledger
+
+#else // ! (LOGGING_ON && TIMERS_ON)
+
+#define TRACE_START(lvl, msg, name)
+#define TRACE_STOP(name)
+#define TRACE_FINISH(name)
+
+#define DEBUG_START(name, msg)
+#define DEBUG_START_(name, cat, msg)
+#define DEBUG_STOP(name)
+#define DEBUG_FINISH(name)
+
+#define INFO_START(name, msg)
+#define INFO_STOP(name)
+#define INFO_FINISH(name)
+
+#endif // TIMERS_ON
+
+/*@}*/
+
+/*
+ * These files define the other internal facilities.
+ */
+
+#include "error.h"
+
+enum caught_signal_t {
+ NONE_CAUGHT,
+ INTERRUPTED,
+ PIPE_CLOSED
+};
+
+extern caught_signal_t caught_signal;
+
+void sigint_handler(int sig);
+void sigpipe_handler(int sig);
+
+inline void check_for_signal() {
+ switch (caught_signal) {
+ case NONE_CAUGHT:
+ break;
+ case INTERRUPTED:
+ throw std::runtime_error(_("Interrupted by user (use Control-D to quit)"));
+ case PIPE_CLOSED:
+ throw std::runtime_error(_("Pipe terminated"));
+ }
+}
+
+/**
+ * @name General utility functions
+ */
+/*@{*/
+
+#define foreach BOOST_FOREACH
+
+namespace ledger {
+
+template <typename T, typename U>
+inline T& downcast(U& object) {
+ return *polymorphic_downcast<T *>(&object);
+}
+
+path resolve_path(const path& pathname);
+
+#ifdef HAVE_REALPATH
+extern "C" char * realpath(const char *, char resolved_path[]);
+#endif
+
+inline const string& either_or(const string& first,
+ const string& second) {
+ return first.empty() ? second : first;
+}
+
+inline char * skip_ws(char * ptr) {
+ while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')
+ ptr++;
+ return ptr;
+}
+
+inline char * trim_ws(char * ptr) {
+ std::size_t len = std::strlen(ptr);
+ int i = int(len) - 1;
+ while (i >= 0 && (ptr[i] == ' ' || ptr[i] == '\t' || ptr[i] == '\n'))
+ ptr[i--] = '\0';
+ return skip_ws(ptr);
+}
+
+inline char * next_element(char * buf, bool variable = false) {
+ for (char * p = buf; *p; p++) {
+ if (! (*p == ' ' || *p == '\t'))
+ continue;
+
+ if (! variable) {
+ *p = '\0';
+ return skip_ws(p + 1);
+ }
+ else if (*p == '\t') {
+ *p = '\0';
+ return skip_ws(p + 1);
+ }
+ else if (*(p + 1) == ' ') {
+ *p = '\0';
+ return skip_ws(p + 2);
+ }
+ }
+ return NULL;
+}
+
+inline char peek_next_nonws(std::istream& in) {
+ char c = static_cast<char>(in.peek());
+ while (in.good() && ! in.eof() && std::isspace(c)) {
+ in.get(c);
+ c = static_cast<char>(in.peek());
+ }
+ return c;
+}
+
+#define READ_INTO(str, targ, size, var, cond) { \
+ char * _p = targ; \
+ var = static_cast<char>(str.peek()); \
+ while (str.good() && ! str.eof() && var != '\n' && \
+ (cond) && _p - targ < size) { \
+ str.get(var); \
+ if (str.eof()) \
+ break; \
+ if (var == '\\') { \
+ str.get(var); \
+ if (in.eof()) \
+ break; \
+ switch (var) { \
+ case 'b': var = '\b'; break; \
+ case 'f': var = '\f'; break; \
+ case 'n': var = '\n'; break; \
+ case 'r': var = '\r'; break; \
+ case 't': var = '\t'; break; \
+ case 'v': var = '\v'; break; \
+ default: break; \
+ } \
+ } \
+ *_p++ = var; \
+ var = static_cast<char>(str.peek()); \
+ } \
+ *_p = '\0'; \
+ }
+
+#define READ_INTO_(str, targ, size, var, idx, cond) { \
+ char * _p = targ; \
+ var = static_cast<char>(str.peek()); \
+ while (str.good() && ! str.eof() && var != '\n' && \
+ (cond) && _p - targ < size) { \
+ str.get(var); \
+ if (str.eof()) \
+ break; \
+ idx++; \
+ if (var == '\\') { \
+ str.get(var); \
+ if (in.eof()) \
+ break; \
+ switch (var) { \
+ case 'b': var = '\b'; break; \
+ case 'f': var = '\f'; break; \
+ case 'n': var = '\n'; break; \
+ case 'r': var = '\r'; break; \
+ case 't': var = '\t'; break; \
+ case 'v': var = '\v'; break; \
+ default: break; \
+ } \
+ idx++; \
+ } \
+ *_p++ = var; \
+ var = static_cast<char>(str.peek()); \
+ } \
+ *_p = '\0'; \
+ }
+
+inline string to_hex(uint_least32_t * message_digest, const int len = 1)
+{
+ std::ostringstream buf;
+
+ for(int i = 0; i < 5 ; i++) {
+ buf.width(8);
+ buf.fill('0');
+ buf << std::hex << message_digest[i];
+ if (i + 1 >= len)
+ break; // only output the first LEN dwords
+ }
+ return buf.str();
+}
+
+class push_xml
+{
+ std::ostream& out;
+ string tag;
+ bool leave_open;
+
+public:
+ push_xml(std::ostream& _out, const string& _tag, bool has_attrs = false,
+ bool _leave_open = false)
+ : out(_out), tag(_tag), leave_open(_leave_open) {
+ out << '<' << tag;
+ if (! has_attrs)
+ out << '>';
+ }
+ ~push_xml() {
+ if (! leave_open)
+ out << "</" << tag << '>';
+ }
+
+ void close_attrs() {
+ out << '>';
+ }
+
+ static string guard(const string& str) {
+ std::ostringstream buf;
+ foreach (const char& ch, str) {
+ switch (ch) {
+ case '<':
+ buf << "&lt;";
+ break;
+ case '>':
+ buf << "&gt;";
+ break;
+ case '&':
+ buf << "&amp;";
+ break;
+ default:
+ buf << ch;
+ break;
+ }
+ }
+ return buf.str();
+ }
+};
+
+extern const string version;
+
+} // namespace ledger
+
+/*@}*/
+
+#endif // _UTILS_H
diff --git a/src/value.cc b/src/value.cc
new file mode 100644
index 00000000..cce4c4e8
--- /dev/null
+++ b/src/value.cc
@@ -0,0 +1,1864 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "value.h"
+#include "commodity.h"
+#include "annotate.h"
+#include "pool.h"
+#include "unistring.h" // for justify()
+
+namespace ledger {
+
+intrusive_ptr<value_t::storage_t> value_t::true_value;
+intrusive_ptr<value_t::storage_t> value_t::false_value;
+
+value_t::storage_t& value_t::storage_t::operator=(const value_t::storage_t& rhs)
+{
+ type = rhs.type;
+
+ switch (type) {
+ case BALANCE:
+ data = new balance_t(*boost::get<balance_t *>(rhs.data));
+ break;
+ case SEQUENCE:
+ data = new sequence_t(*boost::get<sequence_t *>(rhs.data));
+ break;
+
+ default:
+ data = rhs.data;
+ break;
+ }
+
+ return *this;
+}
+
+void value_t::initialize()
+{
+ true_value = new storage_t;
+ true_value->type = BOOLEAN;
+ true_value->data = true;
+
+ false_value = new storage_t;
+ false_value->type = BOOLEAN;
+ false_value->data = false;
+}
+
+void value_t::shutdown()
+{
+ true_value = intrusive_ptr<storage_t>();
+ false_value = intrusive_ptr<storage_t>();
+}
+
+value_t::operator bool() const
+{
+ switch (type()) {
+ case VOID:
+ return false;
+ case BOOLEAN:
+ return as_boolean();
+ case DATETIME:
+ return is_valid(as_datetime());
+ case DATE:
+ return is_valid(as_date());
+ case INTEGER:
+ return as_long();
+ case AMOUNT:
+ return as_amount();
+ case BALANCE:
+ return as_balance();
+ case STRING:
+ return ! as_string().empty();
+ case MASK: {
+ std::ostringstream out;
+ out << *this;
+ throw_(value_error,
+ _("Cannot determine truth of %1 (did you mean 'account =~ %2'?)")
+ << label() << out.str());
+ }
+ case SEQUENCE:
+ if (! as_sequence().empty()) {
+ foreach (const value_t& value, as_sequence()) {
+ if (value)
+ return true;
+ }
+ }
+ return false;
+ case SCOPE:
+ return as_scope() != NULL;
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot determine truth of %1") << label());
+ return false;
+}
+
+void value_t::set_type(type_t new_type)
+{
+ if (new_type == VOID) {
+#if BOOST_VERSION >= 103700
+ storage.reset();
+#else
+ storage = intrusive_ptr<storage_t>();
+#endif
+ } else {
+ if (! storage || storage->refc > 1)
+ storage = new storage_t;
+ else
+ storage->destroy();
+ storage->type = new_type;
+ }
+}
+
+bool value_t::to_boolean() const
+{
+ if (is_boolean()) {
+ return as_boolean();
+ } else {
+ value_t temp(*this);
+ temp.in_place_cast(BOOLEAN);
+ return temp.as_boolean();
+ }
+}
+
+datetime_t value_t::to_datetime() const
+{
+ if (is_datetime()) {
+ return as_datetime();
+ } else {
+ value_t temp(*this);
+ temp.in_place_cast(DATETIME);
+ return temp.as_datetime();
+ }
+}
+
+date_t value_t::to_date() const
+{
+ if (is_date()) {
+ return as_date();
+ } else {
+ value_t temp(*this);
+ temp.in_place_cast(DATE);
+ return temp.as_date();
+ }
+}
+
+int value_t::to_int() const
+{
+ if (is_long()) {
+ return static_cast<int>(as_long());
+ } else {
+ value_t temp(*this);
+ temp.in_place_cast(INTEGER);
+ return static_cast<int>(temp.as_long());
+ }
+}
+
+long value_t::to_long() const
+{
+ if (is_long()) {
+ return as_long();
+ } else {
+ value_t temp(*this);
+ temp.in_place_cast(INTEGER);
+ return temp.as_long();
+ }
+}
+
+amount_t value_t::to_amount() const
+{
+ if (is_amount()) {
+ return as_amount();
+ } else {
+ value_t temp(*this);
+ temp.in_place_cast(AMOUNT);
+ return temp.as_amount();
+ }
+}
+
+balance_t value_t::to_balance() const
+{
+ if (is_balance()) {
+ return as_balance();
+ } else {
+ value_t temp(*this);
+ temp.in_place_cast(BALANCE);
+ return temp.as_balance();
+ }
+}
+
+string value_t::to_string() const
+{
+ if (is_string()) {
+ return as_string();
+ } else {
+ value_t temp(*this);
+ temp.in_place_cast(STRING);
+ return temp.as_string();
+ }
+}
+
+mask_t value_t::to_mask() const
+{
+ if (is_mask()) {
+ return as_mask();
+ } else {
+ value_t temp(*this);
+ temp.in_place_cast(MASK);
+ return temp.as_mask();
+ }
+}
+
+value_t::sequence_t value_t::to_sequence() const
+{
+ if (is_sequence()) {
+ return as_sequence();
+ } else {
+ value_t temp(*this);
+ temp.in_place_cast(SEQUENCE);
+ return temp.as_sequence();
+ }
+}
+
+
+void value_t::in_place_simplify()
+{
+#if defined(DEBUG_ON)
+ LOGGER("value.simplify");
+#endif
+
+ if (is_realzero()) {
+ DEBUG_("Zeroing type " << static_cast<int>(type()));
+ set_long(0L);
+ return;
+ }
+
+ if (is_balance() && as_balance().single_amount()) {
+ DEBUG_("Reducing balance to amount");
+ DEBUG_("as a balance it looks like: " << *this);
+ in_place_cast(AMOUNT);
+ DEBUG_("as an amount it looks like: " << *this);
+ }
+
+#ifdef REDUCE_TO_INTEGER // this is off by default
+ if (is_amount() && ! as_amount().has_commodity() &&
+ as_amount().fits_in_long()) {
+ DEBUG_("Reducing amount to integer");
+ in_place_cast(INTEGER);
+ }
+#endif
+}
+
+value_t value_t::number() const
+{
+ switch (type()) {
+ case VOID:
+ return 0L;
+ case BOOLEAN:
+ return as_boolean() ? 1L : 0L;
+ case INTEGER:
+ return as_long();
+ case AMOUNT:
+ return as_amount().number();
+ case BALANCE:
+ return as_balance().number();
+ case SEQUENCE:
+ if (! as_sequence().empty()) {
+ value_t temp;
+ foreach (const value_t& value, as_sequence())
+ temp += value.number();
+ return temp;
+ }
+ break;
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot determine numeric value of %1") << label());
+ return false;
+}
+
+value_t& value_t::operator+=(const value_t& val)
+{
+ if (is_string()) {
+ if (val.is_string())
+ as_string_lval() += val.as_string();
+ else
+ as_string_lval() += val.to_string();
+ return *this;
+ }
+ else if (is_sequence()) {
+ if (val.is_sequence()) {
+ if (size() == val.size()) {
+ sequence_t::iterator i = begin();
+ sequence_t::const_iterator j = val.begin();
+
+ for (; i != end(); i++, j++)
+ *i += *j;
+ } else {
+ throw_(value_error, _("Cannot add sequences of different lengths"));
+ }
+ } else {
+ as_sequence_lval().push_back(val);
+ }
+ return *this;
+ }
+
+ switch (type()) {
+ case DATETIME:
+ switch (val.type()) {
+ case INTEGER:
+ as_datetime_lval() +=
+ time_duration_t(0, 0, static_cast<time_duration_t::sec_type>(val.as_long()));
+ return *this;
+ case AMOUNT:
+ as_datetime_lval() +=
+ time_duration_t(0, 0, static_cast<time_duration_t::sec_type>
+ (val.as_amount().to_long()));
+ return *this;
+ default:
+ break;
+ }
+ break;
+
+ case DATE:
+ switch (val.type()) {
+ case INTEGER:
+ as_date_lval() += gregorian::date_duration(val.as_long());
+ return *this;
+ case AMOUNT:
+ as_date_lval() += gregorian::date_duration(val.as_amount().to_long());
+ return *this;
+ default:
+ break;
+ }
+ break;
+
+ case INTEGER:
+ switch (val.type()) {
+ case INTEGER:
+ as_long_lval() += val.as_long();
+ return *this;
+ case AMOUNT:
+ if (val.as_amount().has_commodity()) {
+ in_place_cast(BALANCE);
+ return *this += val;
+ }
+ in_place_cast(AMOUNT);
+ as_amount_lval() += val.as_amount();
+ return *this;
+ case BALANCE:
+ in_place_cast(BALANCE);
+ as_balance_lval() += val.as_balance();
+ return *this;
+ default:
+ break;
+ }
+ break;
+
+ case AMOUNT:
+ switch (val.type()) {
+ case INTEGER:
+ if (as_amount().has_commodity()) {
+ in_place_cast(BALANCE);
+ return *this += val;
+ } else {
+ as_amount_lval() += val.as_long();
+ return *this;
+ }
+ break;
+
+ case AMOUNT:
+ if (as_amount().commodity() != val.as_amount().commodity()) {
+ in_place_cast(BALANCE);
+ return *this += val;
+ } else {
+ as_amount_lval() += val.as_amount();
+ return *this;
+ }
+ break;
+
+ case BALANCE:
+ in_place_cast(BALANCE);
+ as_balance_lval() += val.as_balance();
+ return *this;
+
+ default:
+ break;
+ }
+ break;
+
+ case BALANCE:
+ switch (val.type()) {
+ case INTEGER:
+ as_balance_lval() += val.to_amount();
+ return *this;
+ case AMOUNT:
+ as_balance_lval() += val.as_amount();
+ return *this;
+ case BALANCE:
+ as_balance_lval() += val.as_balance();
+ return *this;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot add %1 to %2") << val.label() << label());
+ return *this;
+}
+
+value_t& value_t::operator-=(const value_t& val)
+{
+ if (is_sequence()) {
+ sequence_t& seq(as_sequence_lval());
+
+ if (val.is_sequence()) {
+ if (size() == val.size()) {
+ sequence_t::iterator i = begin();
+ sequence_t::const_iterator j = val.begin();
+
+ for (; i != end(); i++, j++)
+ *i -= *j;
+ } else {
+ throw_(value_error, _("Cannot subtract sequences of different lengths"));
+ }
+ } else {
+ sequence_t::iterator i = std::find(seq.begin(), seq.end(), val);
+ if (i != seq.end())
+ seq.erase(i);
+ }
+ return *this;
+ }
+
+ switch (type()) {
+ case DATETIME:
+ switch (val.type()) {
+ case INTEGER:
+ as_datetime_lval() -=
+ time_duration_t(0, 0, static_cast<time_duration_t::sec_type>(val.as_long()));
+ return *this;
+ case AMOUNT:
+ as_datetime_lval() -=
+ time_duration_t(0, 0, static_cast<time_duration_t::sec_type>
+ (val.as_amount().to_long()));
+ return *this;
+ default:
+ break;
+ }
+ break;
+
+ case DATE:
+ switch (val.type()) {
+ case INTEGER:
+ as_date_lval() -= gregorian::date_duration(val.as_long());
+ return *this;
+ case AMOUNT:
+ as_date_lval() -= gregorian::date_duration(val.as_amount().to_long());
+ return *this;
+ default:
+ break;
+ }
+ break;
+
+ case INTEGER:
+ switch (val.type()) {
+ case INTEGER:
+ as_long_lval() -= val.as_long();
+ return *this;
+ case AMOUNT:
+ in_place_cast(AMOUNT);
+ as_amount_lval() -= val.as_amount();
+ in_place_simplify();
+ return *this;
+ case BALANCE:
+ in_place_cast(BALANCE);
+ as_balance_lval() -= val.as_balance();
+ in_place_simplify();
+ return *this;
+ default:
+ break;
+ }
+ break;
+
+ case AMOUNT:
+ switch (val.type()) {
+ case INTEGER:
+ if (as_amount().has_commodity()) {
+ in_place_cast(BALANCE);
+ *this -= val;
+ in_place_simplify();
+ return *this;
+ } else {
+ as_amount_lval() -= val.as_long();
+ in_place_simplify();
+ return *this;
+ }
+ break;
+
+ case AMOUNT:
+ if (as_amount().commodity() != val.as_amount().commodity()) {
+ in_place_cast(BALANCE);
+ *this -= val;
+ in_place_simplify();
+ return *this;
+ } else {
+ as_amount_lval() -= val.as_amount();
+ in_place_simplify();
+ return *this;
+ }
+ break;
+
+ case BALANCE:
+ in_place_cast(BALANCE);
+ as_balance_lval() -= val.as_balance();
+ in_place_simplify();
+ return *this;
+
+ default:
+ break;
+ }
+ break;
+
+ case BALANCE:
+ switch (val.type()) {
+ case INTEGER:
+ as_balance_lval() -= val.to_amount();
+ in_place_simplify();
+ return *this;
+ case AMOUNT:
+ as_balance_lval() -= val.as_amount();
+ in_place_simplify();
+ return *this;
+ case BALANCE:
+ as_balance_lval() -= val.as_balance();
+ in_place_simplify();
+ return *this;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot subtract %1 from %2") << val.label() << label());
+
+ return *this;
+}
+
+value_t& value_t::operator*=(const value_t& val)
+{
+ if (is_string()) {
+ string temp;
+ long count = val.to_long();
+ for (long i = 0; i < count; i++)
+ temp += as_string();
+ set_string(temp);
+ return *this;
+ }
+ else if (is_sequence()) {
+ value_t temp;
+ long count = val.to_long();
+ for (long i = 0; i < count; i++)
+ temp += as_sequence();
+ return *this = temp;
+ }
+
+ switch (type()) {
+ case INTEGER:
+ switch (val.type()) {
+ case INTEGER:
+ as_long_lval() *= val.as_long();
+ return *this;
+ case AMOUNT:
+ set_amount(val.as_amount() * as_long());
+ return *this;
+ default:
+ break;
+ }
+ break;
+
+ case AMOUNT:
+ switch (val.type()) {
+ case INTEGER:
+ as_amount_lval() *= val.as_long();
+ return *this;
+ case AMOUNT:
+ as_amount_lval() *= val.as_amount();
+ return *this;
+ case BALANCE:
+ if (val.as_balance().single_amount()) {
+ as_amount_lval() *= val.simplified().as_amount();
+ return *this;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case BALANCE:
+ switch (val.type()) {
+ case INTEGER:
+ as_balance_lval() *= val.as_long();
+ return *this;
+ case AMOUNT:
+ if (as_balance().single_amount()) {
+ in_place_simplify();
+ as_amount_lval() *= val.as_amount();
+ return *this;
+ }
+ else if (! val.as_amount().has_commodity()) {
+ as_balance_lval() *= val.as_amount();
+ return *this;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ DEBUG("value.multiply.error", "Left: " << *this);
+ DEBUG("value.multiply.error", "Right: " << val);
+
+ throw_(value_error, _("Cannot multiply %1 with %2") << label() << val.label());
+
+ return *this;
+}
+
+value_t& value_t::operator/=(const value_t& val)
+{
+ switch (type()) {
+ case INTEGER:
+ switch (val.type()) {
+ case INTEGER:
+ as_long_lval() /= val.as_long();
+ return *this;
+ case AMOUNT:
+ set_amount(val.as_amount() / as_long());
+ return *this;
+ default:
+ break;
+ }
+ break;
+
+ case AMOUNT:
+ switch (val.type()) {
+ case INTEGER:
+ as_amount_lval() /= val.as_long();
+ return *this;
+
+ case AMOUNT:
+ as_amount_lval() /= val.as_amount();
+ return *this;
+ case BALANCE:
+ if (val.as_balance().single_amount()) {
+ value_t simpler(val.simplified());
+ switch (simpler.type()) {
+ case INTEGER:
+ as_amount_lval() /= simpler.as_long();
+ break;
+ case AMOUNT:
+ as_amount_lval() /= simpler.as_amount();
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ return *this;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case BALANCE:
+ switch (val.type()) {
+ case INTEGER:
+ as_balance_lval() /= val.as_long();
+ return *this;
+ case AMOUNT:
+ if (as_balance().single_amount()) {
+ in_place_simplify();
+ as_amount_lval() /= val.as_amount();
+ return *this;
+ }
+ else if (! val.as_amount().has_commodity()) {
+ as_balance_lval() /= val.as_amount();
+ return *this;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot divide %1 by %2") << label() << val.label());
+
+ return *this;
+}
+
+
+bool value_t::is_equal_to(const value_t& val) const
+{
+ switch (type()) {
+ case VOID:
+ return val.type() == VOID;
+
+ case BOOLEAN:
+ if (val.is_boolean())
+ return as_boolean() == val.as_boolean();
+ break;
+
+ case DATETIME:
+ if (val.is_datetime())
+ return as_datetime() == val.as_datetime();
+ break;
+
+ case DATE:
+ if (val.is_date())
+ return as_date() == val.as_date();
+ break;
+
+ case INTEGER:
+ switch (val.type()) {
+ case INTEGER:
+ return as_long() == val.as_long();
+ case AMOUNT:
+ return val.as_amount() == to_amount();
+ case BALANCE:
+ return val.as_balance() == to_amount();
+ default:
+ break;
+ }
+ break;
+
+ case AMOUNT:
+ switch (val.type()) {
+ case INTEGER:
+ return as_amount() == val.as_long();
+ case AMOUNT:
+ return as_amount() == val.as_amount();
+ case BALANCE:
+ return val.as_balance() == as_amount();
+ default:
+ break;
+ }
+ break;
+
+ case BALANCE:
+ switch (val.type()) {
+ case INTEGER:
+ return as_balance() == val.to_amount();
+ case AMOUNT:
+ return as_balance() == val.as_amount();
+ case BALANCE:
+ return as_balance() == val.as_balance();
+ default:
+ break;
+ }
+ break;
+
+ case STRING:
+ if (val.is_string())
+ return as_string() == val.as_string();
+ break;
+
+ case MASK:
+ if (val.is_mask())
+ return as_mask() == val.as_mask();
+ break;
+
+ case SEQUENCE:
+ if (val.is_sequence())
+ return as_sequence() == val.as_sequence();
+ break;
+
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot compare %1 by %2") << label() << val.label());
+
+ return *this;
+}
+
+bool value_t::is_less_than(const value_t& val) const
+{
+ switch (type()) {
+ case DATETIME:
+ if (val.is_datetime())
+ return as_datetime() < val.as_datetime();
+ break;
+
+ case DATE:
+ if (val.is_date())
+ return as_date() < val.as_date();
+ break;
+
+ case INTEGER:
+ switch (val.type()) {
+ case INTEGER:
+ return as_long() < val.as_long();
+ case AMOUNT:
+ return val.as_amount() >= as_long();
+ default:
+ break;
+ }
+ break;
+
+ case AMOUNT:
+ switch (val.type()) {
+ case INTEGER:
+ return as_amount() < val.as_long();
+ case AMOUNT:
+ try {
+ return as_amount() < val.as_amount();
+ }
+ catch (const amount_error&) {
+ return compare_amount_commodities()(&as_amount(), &val.as_amount());
+ }
+ default:
+ break;
+ }
+ break;
+
+ case BALANCE:
+ switch (val.type()) {
+ case INTEGER:
+ case AMOUNT: {
+ if (val.is_nonzero())
+ break;
+
+ bool no_amounts = true;
+ foreach (const balance_t::amounts_map::value_type& pair,
+ as_balance().amounts) {
+ if (pair.second >= 0L)
+ return false;
+ no_amounts = false;
+ }
+ return ! no_amounts;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case STRING:
+ if (val.is_string())
+ return as_string() < val.as_string();
+ break;
+
+ case SEQUENCE:
+ switch (val.type()) {
+ case INTEGER:
+ case AMOUNT: {
+ if (val.is_nonzero())
+ break;
+
+ bool no_amounts = true;
+ foreach (const value_t& value, as_sequence()) {
+ if (value >= 0L)
+ return false;
+ no_amounts = false;
+ }
+ return ! no_amounts;
+ }
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot compare %1 to %2") << label() << val.label());
+
+ return *this;
+}
+
+bool value_t::is_greater_than(const value_t& val) const
+{
+ switch (type()) {
+ case DATETIME:
+ if (val.is_datetime())
+ return as_datetime() > val.as_datetime();
+ break;
+
+ case DATE:
+ if (val.is_date())
+ return as_date() > val.as_date();
+ break;
+
+ case INTEGER:
+ switch (val.type()) {
+ case INTEGER:
+ return as_long() > val.as_long();
+ case AMOUNT:
+ return val.as_amount() > as_long();
+ default:
+ break;
+ }
+ break;
+
+ case AMOUNT:
+ switch (val.type()) {
+ case INTEGER:
+ return as_amount() > val.as_long();
+ case AMOUNT:
+ return as_amount() > val.as_amount();
+ default:
+ break;
+ }
+ break;
+
+ case BALANCE:
+ switch (val.type()) {
+ case INTEGER:
+ case AMOUNT: {
+ if (val.is_nonzero())
+ break;
+
+ bool no_amounts = true;
+ foreach (const balance_t::amounts_map::value_type& pair,
+ as_balance().amounts) {
+ if (pair.second <= 0L)
+ return false;
+ no_amounts = false;
+ }
+ return ! no_amounts;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case STRING:
+ if (val.is_string())
+ return as_string() > val.as_string();
+ break;
+
+ case SEQUENCE:
+ switch (val.type()) {
+ case INTEGER:
+ case AMOUNT: {
+ if (val.is_nonzero())
+ break;
+
+ bool no_amounts = true;
+ foreach (const value_t& value, as_sequence()) {
+ if (value <= 0L)
+ return false;
+ no_amounts = false;
+ }
+ return ! no_amounts;
+ }
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot compare %1 to %2") << label() << val.label());
+
+ return *this;
+}
+
+void value_t::in_place_cast(type_t cast_type)
+{
+ if (type() == cast_type)
+ return;
+
+ _dup();
+
+ if (cast_type == BOOLEAN) {
+ set_boolean(bool(*this));
+ return;
+ }
+ else if (cast_type == SEQUENCE) {
+ sequence_t temp;
+ if (! is_null())
+ temp.push_back(*this);
+ set_sequence(temp);
+ return;
+ }
+
+ switch (type()) {
+ case BOOLEAN:
+ switch (cast_type) {
+ case AMOUNT:
+ set_amount(as_boolean() ? 1L : 0L);
+ return;
+ case STRING:
+ set_string(as_boolean() ? "true" : "false");
+ return;
+ default:
+ break;
+ }
+ break;
+
+ case DATE:
+ switch (cast_type) {
+ case DATETIME:
+ set_datetime(datetime_t(as_date(), time_duration(0, 0, 0, 0)));
+ return;
+ case STRING:
+ set_string(format_date(as_date(), FMT_WRITTEN));
+ return;
+ default:
+ break;
+ }
+ break;
+ case DATETIME:
+ switch (cast_type) {
+ case DATE:
+ set_date(as_datetime().date());
+ return;
+ case STRING:
+ set_string(format_datetime(as_datetime(), FMT_WRITTEN));
+ return;
+ default:
+ break;
+ }
+ break;
+
+ case INTEGER:
+ switch (cast_type) {
+ case AMOUNT:
+ set_amount(as_long());
+ return;
+ case BALANCE:
+ set_balance(to_amount());
+ return;
+ case STRING:
+ set_string(lexical_cast<string>(as_long()));
+ return;
+ default:
+ break;
+ }
+ break;
+
+ case AMOUNT: {
+ const amount_t& amt(as_amount());
+ switch (cast_type) {
+ case INTEGER:
+ if (amt.is_null())
+ set_long(0L);
+ else
+ set_long(as_amount().to_long());
+ return;
+ case BALANCE:
+ if (amt.is_null())
+ set_balance(balance_t());
+ else
+ set_balance(as_amount());
+ return;
+ case STRING:
+ if (amt.is_null())
+ set_string("");
+ else
+ set_string(as_amount().to_string());
+ return;
+ default:
+ break;
+ }
+ break;
+ }
+
+ case BALANCE: {
+ const balance_t& bal(as_balance());
+ switch (cast_type) {
+ case AMOUNT: {
+ if (bal.amounts.size() == 1) {
+ // Because we are changing the current balance value to an amount
+ // value, and because set_amount takes a reference (and that memory is
+ // about to be repurposed), we must pass in a copy.
+ set_amount(amount_t((*bal.amounts.begin()).second));
+ return;
+ }
+ else if (bal.amounts.size() == 0) {
+ set_amount(0L);
+ return;
+ }
+ else {
+ throw_(value_error, _("Cannot convert %1 with multiple commodities to %2")
+ << label() << label(cast_type));
+ }
+ break;
+ }
+ case STRING:
+ if (bal.is_empty())
+ set_string("");
+ else
+ set_string(as_balance().to_string());
+ return;
+ default:
+ break;
+ }
+ break;
+ }
+
+ case STRING:
+ switch (cast_type) {
+ case INTEGER: {
+ if (all(as_string(), is_digit())) {
+ set_long(lexical_cast<long>(as_string()));
+ return;
+ }
+ break;
+ }
+ case AMOUNT:
+ set_amount(amount_t(as_string()));
+ return;
+ case DATE:
+ set_date(parse_date(as_string()));
+ return;
+ case DATETIME:
+ set_datetime(parse_datetime(as_string()));
+ return;
+ case MASK:
+ set_mask(as_string());
+ return;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ throw_(value_error,
+ _("Cannot convert %1 to %2") << label() << label(cast_type));
+}
+
+void value_t::in_place_negate()
+{
+ switch (type()) {
+ case BOOLEAN:
+ set_boolean(! as_boolean());
+ return;
+ case INTEGER:
+ case DATETIME:
+ set_long(- as_long());
+ return;
+ case DATE:
+ set_long(- as_long());
+ return;
+ case AMOUNT:
+ as_amount_lval().in_place_negate();
+ return;
+ case BALANCE:
+ as_balance_lval().in_place_negate();
+ return;
+ case SEQUENCE: {
+ value_t temp;
+ foreach (const value_t& value, as_sequence())
+ temp.push_back(- value);
+ *this = temp;
+ return;
+ }
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot negate %1") << label());
+}
+
+void value_t::in_place_not()
+{
+ switch (type()) {
+ case BOOLEAN:
+ set_boolean(! as_boolean());
+ return;
+ case INTEGER:
+ case DATETIME:
+ set_boolean(! as_long());
+ return;
+ case DATE:
+ set_boolean(! as_long());
+ return;
+ case AMOUNT:
+ set_boolean(! as_amount());
+ return;
+ case BALANCE:
+ set_boolean(! as_balance());
+ return;
+ case STRING:
+ set_boolean(as_string().empty());
+ return;
+ case SEQUENCE: {
+ value_t temp;
+ foreach (const value_t& value, as_sequence())
+ temp.push_back(! value);
+ *this = temp;
+ return;
+ }
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot 'not' %1") << label());
+}
+
+bool value_t::is_realzero() const
+{
+ switch (type()) {
+ case BOOLEAN:
+ return ! as_boolean();
+ case INTEGER:
+ return as_long() == 0;
+ case DATETIME:
+ return ! is_valid(as_datetime());
+ case DATE:
+ return ! is_valid(as_date());
+ case AMOUNT:
+ return as_amount().is_realzero();
+ case BALANCE:
+ return as_balance().is_realzero();
+ case STRING:
+ return as_string().empty();
+ case SEQUENCE:
+ return as_sequence().empty();
+
+ case SCOPE:
+ return as_scope() == NULL;
+
+ default:
+ throw_(value_error, _("Cannot determine if %1 is really zero") << label());
+ }
+ return false;
+}
+
+bool value_t::is_zero() const
+{
+ switch (type()) {
+ case BOOLEAN:
+ return ! as_boolean();
+ case INTEGER:
+ return as_long() == 0;
+ case DATETIME:
+ return ! is_valid(as_datetime());
+ case DATE:
+ return ! is_valid(as_date());
+ case AMOUNT:
+ return as_amount().is_zero();
+ case BALANCE:
+ return as_balance().is_zero();
+ case STRING:
+ return as_string().empty();
+ case SEQUENCE:
+ return as_sequence().empty();
+
+ case SCOPE:
+ return as_scope() == NULL;
+
+ default:
+ throw_(value_error, _("Cannot determine if %1 is zero") << label());
+ }
+ return false;
+}
+
+value_t value_t::value(const bool primary_only,
+ const optional<datetime_t>& moment,
+ const optional<commodity_t&>& in_terms_of) const
+{
+ switch (type()) {
+ case INTEGER:
+ return NULL_VALUE;
+
+ case AMOUNT:
+ if (optional<amount_t> val =
+ as_amount().value(primary_only, moment, in_terms_of))
+ return *val;
+ return NULL_VALUE;
+
+ case BALANCE:
+ if (optional<balance_t> bal =
+ as_balance().value(primary_only, moment, in_terms_of))
+ return *bal;
+ return NULL_VALUE;
+
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot find the value of %1") << label());
+ return NULL_VALUE;
+}
+
+value_t value_t::price() const
+{
+ switch (type()) {
+ case AMOUNT:
+ return as_amount().price();
+ case BALANCE:
+ return as_balance().price();
+ default:
+ return *this;
+ }
+}
+
+value_t value_t::exchange_commodities(const std::string& commodities,
+ const bool add_prices,
+ const optional<datetime_t>& moment)
+{
+ scoped_array<char> buf(new char[commodities.length() + 1]);
+
+ std::strcpy(buf.get(), commodities.c_str());
+
+ for (char * p = std::strtok(buf.get(), ",");
+ p;
+ p = std::strtok(NULL, ",")) {
+ if (commodity_t * commodity =
+ commodity_pool_t::current_pool->parse_price_expression(p, add_prices,
+ moment)) {
+ value_t result = value(false, moment, *commodity);
+ if (! result.is_null())
+ return result;
+ }
+ }
+ return *this;
+}
+
+void value_t::in_place_reduce()
+{
+ switch (type()) {
+ case AMOUNT:
+ as_amount_lval().in_place_reduce();
+ return;
+ case BALANCE:
+ as_balance_lval().in_place_reduce();
+ return;
+ default:
+ return;
+ }
+
+ //throw_(value_error, "Cannot reduce " << label());
+}
+
+void value_t::in_place_unreduce()
+{
+ switch (type()) {
+ case AMOUNT:
+ as_amount_lval().in_place_unreduce();
+ return;
+ case BALANCE:
+ as_balance_lval().in_place_unreduce();
+ return;
+ default:
+ return;
+ }
+
+ //throw_(value_error, "Cannot reduce " << label());
+}
+
+value_t value_t::abs() const
+{
+ switch (type()) {
+ case INTEGER: {
+ long val = as_long();
+ if (val < 0)
+ return - val;
+ return val;
+ }
+ case AMOUNT:
+ return as_amount().abs();
+ case BALANCE:
+ return as_balance().abs();
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot abs %1") << label());
+ return NULL_VALUE;
+}
+
+void value_t::in_place_round()
+{
+ switch (type()) {
+ case INTEGER:
+ return;
+ case AMOUNT:
+ as_amount_lval().in_place_round();
+ return;
+ case BALANCE:
+ as_balance_lval().in_place_round();
+ return;
+ case SEQUENCE: {
+ value_t temp;
+ foreach (const value_t& value, as_sequence())
+ temp.push_back(value.rounded());
+ *this = temp;
+ return;
+ }
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot set rounding for %1") << label());
+}
+
+void value_t::in_place_truncate()
+{
+ switch (type()) {
+ case INTEGER:
+ return;
+ case AMOUNT:
+ as_amount_lval().in_place_truncate();
+ return;
+ case BALANCE:
+ as_balance_lval().in_place_truncate();
+ return;
+ case SEQUENCE: {
+ value_t temp;
+ foreach (const value_t& value, as_sequence())
+ temp.push_back(value.truncated());
+ *this = temp;
+ return;
+ }
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot truncate %1") << label());
+}
+
+void value_t::in_place_floor()
+{
+ switch (type()) {
+ case INTEGER:
+ return;
+ case AMOUNT:
+ as_amount_lval().in_place_floor();
+ return;
+ case BALANCE:
+ as_balance_lval().in_place_floor();
+ return;
+ case SEQUENCE: {
+ value_t temp;
+ foreach (const value_t& value, as_sequence())
+ temp.push_back(value.floored());
+ *this = temp;
+ return;
+ }
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot floor %1") << label());
+}
+
+void value_t::in_place_unround()
+{
+ switch (type()) {
+ case INTEGER:
+ return;
+ case AMOUNT:
+ as_amount_lval().in_place_unround();
+ return;
+ case BALANCE:
+ as_balance_lval().in_place_unround();
+ return;
+ case SEQUENCE: {
+ value_t temp;
+ foreach (const value_t& value, as_sequence())
+ temp.push_back(value.unrounded());
+ *this = temp;
+ return;
+ }
+ default:
+ break;
+ }
+
+ throw_(value_error, _("Cannot unround %1") << label());
+}
+
+void value_t::annotate(const annotation_t& details)
+{
+ if (is_amount())
+ as_amount_lval().annotate(details);
+ else
+ throw_(value_error, _("Cannot annotate %1") << label());
+}
+
+bool value_t::has_annotation() const
+{
+ if (is_amount())
+ return as_amount().has_annotation();
+ else
+ throw_(value_error,
+ _("Cannot determine whether %1 is annotated") << label());
+ return false;
+}
+
+annotation_t& value_t::annotation()
+{
+ if (is_amount())
+ return as_amount_lval().annotation();
+ else {
+ throw_(value_error, _("Cannot request annotation of %1") << label());
+ return as_amount_lval().annotation(); // quiet g++ warning
+ }
+}
+
+value_t value_t::strip_annotations(const keep_details_t& what_to_keep) const
+{
+ if (what_to_keep.keep_all())
+ return *this;
+
+ switch (type()) {
+ case VOID:
+ case BOOLEAN:
+ case INTEGER:
+ case DATETIME:
+ case DATE:
+ case STRING:
+ case MASK:
+ case SCOPE:
+ return *this;
+
+ case SEQUENCE: {
+ sequence_t temp;
+ foreach (const value_t& value, as_sequence())
+ temp.push_back(value.strip_annotations(what_to_keep));
+ return temp;
+ }
+
+ case AMOUNT:
+ return as_amount().strip_annotations(what_to_keep);
+ case BALANCE:
+ return as_balance().strip_annotations(what_to_keep);
+
+ default:
+ assert(false);
+ break;
+ }
+ assert(false);
+ return NULL_VALUE;
+}
+
+void value_t::print(std::ostream& out,
+ const int first_width,
+ const int latter_width,
+ const bool right_justify,
+ const bool colorize) const
+{
+ if (first_width > 0 &&
+ (! is_amount() || as_amount().is_zero()) &&
+ ! is_balance() && ! is_string()) {
+ out.width(first_width);
+
+ if (right_justify)
+ out << std::right;
+ else
+ out << std::left;
+ }
+
+ switch (type()) {
+ case VOID:
+ out << "";
+ break;
+
+ case BOOLEAN:
+ out << (as_boolean() ? "1" : "0");
+ break;
+
+ case DATETIME:
+ out << format_datetime(as_datetime(), FMT_WRITTEN);
+ break;
+
+ case DATE:
+ out << format_date(as_date(), FMT_WRITTEN);
+ break;
+
+ case INTEGER:
+ if (colorize && as_long() < 0)
+ justify(out, to_string(), first_width, right_justify, true);
+ else
+ out << as_long();
+ break;
+
+ case AMOUNT: {
+ if (as_amount().is_zero()) {
+ out << 0;
+ } else {
+ std::ostringstream buf;
+ buf << as_amount();
+ justify(out, buf.str(), first_width, right_justify,
+ colorize && as_amount().sign() < 0);
+ }
+ break;
+ }
+
+ case BALANCE:
+ as_balance().print(out, first_width, latter_width, right_justify,
+ colorize);
+ break;
+
+ case STRING:
+ if (first_width > 0)
+ justify(out, as_string(), first_width, right_justify);
+ else
+ out << as_string();
+ break;
+
+ case MASK:
+ out << '/' << as_mask() << '/';
+ break;
+
+ case SEQUENCE: {
+ out << '(';
+ bool first = true;
+ foreach (const value_t& value, as_sequence()) {
+ if (first)
+ first = false;
+ else
+ out << ", ";
+
+ value.print(out, first_width, latter_width, right_justify,
+ colorize);
+ }
+ out << ')';
+ break;
+ }
+
+ case SCOPE:
+ out << "<SCOPE>";
+ break;
+
+ default:
+ throw_(value_error, _("Cannot print %1") << label());
+ }
+}
+
+void value_t::dump(std::ostream& out, const bool relaxed) const
+{
+ switch (type()) {
+ case VOID:
+ out << "null";
+ break;
+
+ case BOOLEAN:
+ if (as_boolean())
+ out << "true";
+ else
+ out << "false";
+ break;
+
+ case DATETIME:
+ out << '[' << format_datetime(as_datetime(), FMT_WRITTEN) << ']';
+ break;
+ case DATE:
+ out << '[' << format_date(as_date(), FMT_WRITTEN) << ']';
+ break;
+
+ case INTEGER:
+ out << as_long();
+ break;
+
+ case AMOUNT:
+ if (! relaxed)
+ out << '{';
+ out << as_amount();
+ if (! relaxed)
+ out << '}';
+ break;
+
+ case BALANCE:
+ out << as_balance();
+ break;
+
+ case STRING:
+ out << '"';
+ foreach (const char& ch, as_string()) {
+ switch (ch) {
+ case '"':
+ out << "\\\"";
+ break;
+ case '\\':
+ out << "\\\\";
+ break;
+ default:
+ out << ch;
+ break;
+ }
+ }
+ out << '"';
+ break;
+
+ case MASK:
+ out << '/' << as_mask() << '/';
+ break;
+
+ case SCOPE:
+ out << as_scope();
+ break;
+
+ case SEQUENCE: {
+ out << '(';
+ bool first = true;
+ foreach (const value_t& value, as_sequence()) {
+ if (first)
+ first = false;
+ else
+ out << ", ";
+
+ value.dump(out, relaxed);
+ }
+ out << ')';
+ break;
+ }
+
+ default:
+ assert(false);
+ break;
+ }
+}
+
+bool value_t::valid() const
+{
+ switch (type()) {
+ case AMOUNT:
+ return as_amount().valid();
+ case BALANCE:
+ return as_balance().valid();
+ default:
+ break;
+ }
+ return true;
+}
+
+bool sort_value_is_less_than(const std::list<sort_value_t>& left_values,
+ const std::list<sort_value_t>& right_values)
+{
+ std::list<sort_value_t>::const_iterator left_iter = left_values.begin();
+ std::list<sort_value_t>::const_iterator right_iter = right_values.begin();
+
+ while (left_iter != left_values.end() && right_iter != right_values.end()) {
+ // Don't even try to sort balance values
+ if (! (*left_iter).value.is_balance() &&
+ ! (*right_iter).value.is_balance()) {
+ DEBUG("value.sort",
+ " Comparing " << (*left_iter).value << " < " << (*right_iter).value);
+ if ((*left_iter).value < (*right_iter).value) {
+ DEBUG("value.sort", " is less");
+ return ! (*left_iter).inverted;
+ }
+ else if ((*left_iter).value > (*right_iter).value) {
+ DEBUG("value.sort", " is greater");
+ return (*left_iter).inverted;
+ }
+ }
+ left_iter++; right_iter++;
+ }
+
+ assert(left_iter == left_values.end());
+ assert(right_iter == right_values.end());
+
+ return false;
+}
+
+void to_xml(std::ostream& out, const value_t& value)
+{
+ switch (value.type()) {
+ case value_t::VOID:
+ out << "<void />";
+ break;
+ case value_t::BOOLEAN: {
+ push_xml y(out, "boolean");
+ out << (value.as_boolean() ? "true" : "false");
+ break;
+ }
+ case value_t::INTEGER: {
+ push_xml y(out, "integer");
+ out << value.as_long();
+ break;
+ }
+
+ case value_t::AMOUNT:
+ to_xml(out, value.as_amount());
+ break;
+ case value_t::BALANCE:
+ to_xml(out, value.as_balance());
+ break;
+
+ case value_t::DATETIME:
+ to_xml(out, value.as_datetime());
+ break;
+ case value_t::DATE:
+ to_xml(out, value.as_date());
+ break;
+ case value_t::STRING: {
+ push_xml y(out, "string");
+ out << y.guard(value.as_string());
+ break;
+ }
+ case value_t::MASK:
+ to_xml(out, value.as_mask());
+ break;
+
+ case value_t::SEQUENCE: {
+ push_xml y(out, "sequence");
+ foreach (const value_t& member, value.as_sequence())
+ to_xml(out, member);
+ break;
+ }
+
+ case value_t::SCOPE:
+ default:
+ assert(false);
+ break;
+ }
+}
+
+} // namespace ledger
diff --git a/src/value.h b/src/value.h
new file mode 100644
index 00000000..ffbb89e8
--- /dev/null
+++ b/src/value.h
@@ -0,0 +1,998 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup math
+ */
+
+/**
+ * @file value.h
+ * @author John Wiegley
+ *
+ * @ingroup math
+ *
+ * @brief Abstract dynamic type representing various numeric types
+ *
+ * A value_t object can be one of many types, and changes its type
+ * dynamically based on how it is used. For example, if you assign
+ * the number 10 to a value object, it's internal type will be
+ * INTEGER.
+ */
+#ifndef _VALUE_H
+#define _VALUE_H
+
+#include "balance.h" // includes amount.h
+#include "mask.h"
+
+namespace ledger {
+
+DECLARE_EXCEPTION(value_error, std::runtime_error);
+
+class scope_t;
+
+/**
+ * @class value_t
+ *
+ * @brief Dynamic type representing various numeric types.
+ *
+ * The following type is a polymorphous value type used solely for
+ * performance reasons. The alternative is to compute value
+ * expressions (valexpr.cc) in terms of the largest data type,
+ * balance_t. This was found to be prohibitively expensive, especially
+ * when large logic chains were involved, since many temporary
+ * allocations would occur for every operator. With value_t, and the
+ * fact that logic chains only need boolean values to continue, no
+ * memory allocations need to take place at all.
+ */
+class value_t
+ : public ordered_field_operators<value_t,
+ equality_comparable<value_t, balance_t,
+ additive<value_t, balance_t,
+ multiplicative<value_t, balance_t,
+ ordered_field_operators<value_t, amount_t,
+ ordered_field_operators<value_t, double,
+ ordered_field_operators<value_t, unsigned long,
+ ordered_field_operators<value_t, long> > > > > > > >
+{
+public:
+ /**
+ * The sequence_t member type abstracts the type used to represent a
+ * resizable "array" of value_t objects.
+ */
+ typedef std::deque<value_t> sequence_t;
+ typedef sequence_t::iterator iterator;
+ typedef sequence_t::const_iterator const_iterator;
+ typedef sequence_t::difference_type difference_type;
+
+ /**
+ * type_t gives the type of the data contained or referenced by a
+ * value_t object. Use the type() method to get a value of type
+ * type_t.
+ */
+ enum type_t {
+ VOID, // a null value (i.e., uninitialized)
+ BOOLEAN, // a boolean
+ DATETIME, // a date and time (Boost posix_time)
+ DATE, // a date (Boost gregorian::date)
+ INTEGER, // a signed integer value
+ AMOUNT, // a ledger::amount_t
+ BALANCE, // a ledger::balance_t
+ STRING, // a string object
+ MASK, // a regular expression mask
+ SEQUENCE, // a vector of value_t objects
+ SCOPE // a pointer to a scope
+ };
+
+private:
+ class storage_t
+ {
+ friend class value_t;
+
+ /**
+ * The `data' member holds the actual bytes relating to whatever
+ * has been stuffed into this storage object. There is a set of
+ * asserts in value.cc to guarantee that the sizeof expression
+ * used here is indeed at least as big as the largest object that
+ * will ever be copied into `data'.
+ *
+ * The `type' member holds the value_t::type_t value representing
+ * the type of the object stored.
+ */
+ variant<bool, // BOOLEAN
+ datetime_t, // DATETIME
+ date_t, // DATE
+ long, // INTEGER
+ amount_t, // AMOUNT
+ balance_t *, // BALANCE
+ string, // STRING
+ mask_t, // MASK
+ sequence_t *, // SEQUENCE
+ scope_t * // SCOPE
+ > data;
+
+ type_t type;
+
+ /**
+ * `refc' holds the current reference count for each storage_t
+ * object.
+ */
+ mutable int refc;
+
+ /**
+ * Constructor. Since all storage object are assigned to after
+ * construction, the only constructors allowed are explicit, and
+ * copy (see below). The default starting type is VOID, which
+ * should rarely ever be seen in practice, since the first thing
+ * that value_t typically does is to assign a valid value.
+ */
+ explicit storage_t() : type(VOID), refc(0) {
+ TRACE_CTOR(value_t::storage_t, "");
+ }
+
+ public: // so `checked_delete' can access it
+ /**
+ * Destructor. Must only be called when the reference count has
+ * reached zero. The `destroy' method is used to do the actual
+ * cleanup of the data, since it's quite possible for `destroy' to
+ * be called while the object is still active -- to clear the
+ * stored data for subsequent reuse of the storage_t object.
+ */
+ ~storage_t() {
+ TRACE_DTOR(value_t::storage_t);
+ VERIFY(refc == 0);
+ destroy();
+ }
+
+ private:
+ /**
+ * Assignment and copy operators. These are called when making a
+ * new copy of a storage object in order to modify the copy.
+ */
+ explicit storage_t(const storage_t& rhs)
+ : type(rhs.type), refc(0) {
+ TRACE_CTOR(value_t::storage_t, "copy");
+ *this = rhs;
+ }
+ storage_t& operator=(const storage_t& rhs);
+
+ /**
+ * Reference counting methods. The intrusive_ptr_* methods are
+ * used by boost::intrusive_ptr to manage the calls to acquire and
+ * release.
+ */
+ void acquire() const {
+ DEBUG("value.storage.refcount",
+ "Acquiring " << this << ", refc now " << refc + 1);
+ VERIFY(refc >= 0);
+ refc++;
+ }
+ void release() const {
+ DEBUG("value.storage.refcount",
+ "Releasing " << this << ", refc now " << refc - 1);
+ VERIFY(refc > 0);
+ if (--refc == 0)
+ checked_delete(this);
+ }
+
+ friend inline void intrusive_ptr_add_ref(value_t::storage_t * storage) {
+ storage->acquire();
+ }
+ friend inline void intrusive_ptr_release(value_t::storage_t * storage) {
+ storage->release();
+ }
+
+ void destroy() {
+ DEBUG("value.storage.refcount", "Destroying " << this);
+ switch (type) {
+ case VOID:
+ return;
+ case BALANCE:
+ checked_delete(boost::get<balance_t *>(data));
+ break;
+ case SEQUENCE:
+ checked_delete(boost::get<sequence_t *>(data));
+ break;
+ default:
+ break;
+ }
+ data = false;
+ type = VOID;
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+ private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & data;
+ ar & type;
+ ar & refc;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+ };
+
+ /**
+ * The actual data for each value_t is kept in reference counted storage.
+ * Data is modified using a copy-on-write policy.
+ */
+ intrusive_ptr<storage_t> storage;
+
+ /**
+ * Make a private copy of the current value (if necessary) so it can
+ * subsequently be modified.
+ */
+ void _dup() {
+ VERIFY(storage);
+ if (storage->refc > 1)
+ storage = new storage_t(*storage.get());
+ }
+
+ /**
+ * Because boolean "true" and "false" are so common, a pair of static
+ * references are kept to prevent the creation of throwaway storage_t
+ * objects just to represent these two common values.
+ */
+ static intrusive_ptr<storage_t> true_value;
+ static intrusive_ptr<storage_t> false_value;
+
+public:
+ static void initialize();
+ static void shutdown();
+
+public:
+ /**
+ * Constructors. value_t objects may be constructed from almost any
+ * value type that they can contain, including variations on those
+ * types (such as long, unsigned long, etc). The ordering of the
+ * methods here reflects the ordering of the constants in type_t
+ * above.
+ *
+ * One constructor of special note is that taking a string or
+ * character pointer as an argument. Because value_t("$100") is
+ * interpreted as a commoditized amount, the form value_t("$100",
+ * true) is required to represent the literal string "$100", and not
+ * the amount "one hundred dollars".
+ */
+ value_t() {
+ TRACE_CTOR(value_t, "");
+ }
+
+ value_t(const bool val) {
+ TRACE_CTOR(value_t, "const bool");
+ set_boolean(val);
+ }
+
+ value_t(const datetime_t& val) {
+ TRACE_CTOR(value_t, "const datetime_t&");
+ set_datetime(val);
+ }
+ value_t(const date_t& val) {
+ TRACE_CTOR(value_t, "const date_t&");
+ set_date(val);
+ }
+
+ value_t(const long val) {
+ TRACE_CTOR(value_t, "const long");
+ set_long(val);
+ }
+ value_t(const unsigned long val) {
+ TRACE_CTOR(value_t, "const unsigned long");
+ set_amount(val);
+ }
+ value_t(const double val) {
+ TRACE_CTOR(value_t, "const double");
+ set_amount(val);
+ }
+ value_t(const amount_t& val) {
+ TRACE_CTOR(value_t, "const amount_t&");
+ set_amount(val);
+ }
+ value_t(const balance_t& val) {
+ TRACE_CTOR(value_t, "const balance_t&");
+ set_balance(val);
+ }
+ value_t(const mask_t& val) {
+ TRACE_CTOR(value_t, "const mask_t&");
+ set_mask(val);
+ }
+
+ explicit value_t(const string& val, bool literal = false) {
+ TRACE_CTOR(value_t, "const string&, bool");
+ if (literal)
+ set_string(val);
+ else
+ set_amount(amount_t(val));
+ }
+ explicit value_t(const char * val, bool literal = false) {
+ TRACE_CTOR(value_t, "const char *");
+ if (literal)
+ set_string(val);
+ else
+ set_amount(amount_t(val));
+ }
+
+ value_t(const sequence_t& val) {
+ TRACE_CTOR(value_t, "const sequence_t&");
+ set_sequence(val);
+ }
+
+ explicit value_t(scope_t * item) {
+ TRACE_CTOR(value_t, "scope_t *");
+ set_scope(item);
+ }
+
+ /**
+ * Destructor. This does not do anything, because the intrusive_ptr
+ * that refers to our storage object will decrease its reference
+ * count itself upon destruction.
+ */
+ ~value_t() {
+ TRACE_DTOR(value_t);
+ }
+
+ /**
+ * Assignment and copy operators. Values are cheaply copied by
+ * simply creating another reference to the other value's storage
+ * object. A true copy is only ever made prior to modification.
+ */
+ value_t(const value_t& val) {
+ TRACE_CTOR(value_t, "copy");
+ *this = val;
+ }
+ value_t& operator=(const value_t& val) {
+ if (! (this == &val || storage == val.storage))
+ storage = val.storage;
+ return *this;
+ }
+
+ /**
+ * Comparison operators. Values can be compared to other values
+ */
+ bool is_equal_to(const value_t& val) const;
+ bool is_less_than(const value_t& val) const;
+ bool is_greater_than(const value_t& val) const;
+
+ template <typename T>
+ bool operator==(const T& amt) const {
+ return is_equal_to(amt);
+ }
+ template <typename T>
+ bool operator<(const T& amt) const {
+ return is_less_than(amt);
+ }
+ template <typename T>
+ bool operator>(const T& amt) const {
+ return is_greater_than(amt);
+ }
+
+ /**
+ * Binary arithmetic operators.
+ *
+ * add(amount_t, optional<amount_t>) allows for the possibility of
+ * adding both an amount and its cost in a single operation.
+ * Otherwise, there is no way to separately represent the "cost"
+ * part of an amount addition statement.
+ */
+ value_t& operator+=(const value_t& val);
+ value_t& operator-=(const value_t& val);
+ value_t& operator*=(const value_t& val);
+ value_t& operator/=(const value_t& val);
+
+ /**
+ * Unary arithmetic operators.
+ */
+ value_t negated() const {
+ value_t temp = *this;
+ temp.in_place_negate();
+ return temp;
+ }
+ void in_place_negate(); // exists for efficiency's sake
+ void in_place_not(); // exists for efficiency's sake
+
+ value_t operator-() const {
+ return negated();
+ }
+
+ value_t abs() const;
+
+ value_t rounded() const {
+ value_t temp(*this);
+ temp.in_place_round();
+ return temp;
+ }
+ void in_place_round();
+
+ value_t truncated() const {
+ value_t temp(*this);
+ temp.in_place_truncate();
+ return temp;
+ }
+ void in_place_truncate();
+
+ value_t floored() const {
+ value_t temp(*this);
+ temp.in_place_floor();
+ return temp;
+ }
+ void in_place_floor();
+
+ value_t unrounded() const {
+ value_t temp(*this);
+ temp.in_place_unround();
+ return temp;
+ }
+ void in_place_unround();
+
+ value_t reduced() const {
+ value_t temp(*this);
+ temp.in_place_reduce();
+ return temp;
+ }
+ void in_place_reduce(); // exists for efficiency's sake
+
+ value_t unreduced() const {
+ value_t temp(*this);
+ temp.in_place_unreduce();
+ return temp;
+ }
+ void in_place_unreduce(); // exists for efficiency's sake
+
+ // Return the "market value" of a given value at a specific time.
+ value_t value(const bool primary_only = false,
+ const optional<datetime_t>& moment = none,
+ const optional<commodity_t&>& in_terms_of = none) const;
+
+ value_t price() const;
+
+ value_t exchange_commodities(const std::string& commodities,
+ const bool add_prices = false,
+ const optional<datetime_t>& moment = none);
+
+ /**
+ * Truth tests.
+ */
+ operator bool() const;
+
+ bool is_nonzero() const {
+ return ! is_zero();
+ }
+
+ bool is_realzero() const;
+ bool is_zero() const;
+ bool is_null() const {
+ if (! storage) {
+ VERIFY(is_type(VOID));
+ return true;
+ } else {
+ VERIFY(! is_type(VOID));
+ return false;
+ }
+ }
+
+ type_t type() const {
+ return storage ? storage->type : VOID;
+ }
+ bool is_type(type_t _type) const {
+ return type() == _type;
+ }
+
+private:
+ void set_type(type_t new_type);
+
+public:
+ /**
+ * Data manipulation methods. A value object may be truth tested for the
+ * existence of every type it can contain:
+ *
+ * is_boolean()
+ * is_long()
+ * is_datetime()
+ * is_date()
+ * is_amount()
+ * is_balance()
+ * is_string()
+ * is_mask()
+ * is_sequence()
+ * is_pointer()
+ *
+ * There are corresponding as_*() methods that represent a value as a
+ * reference to its underlying type. For example, as_long() returns a
+ * reference to a "const long".
+ *
+ * There are also as_*_lval() methods, which represent the underlying data
+ * as a reference to a non-const type. The difference here is that an
+ * _lval() call causes the underlying data to be fully copied before the
+ * resulting reference is returned.
+ *
+ * Lastly, there are corresponding set_*(data) methods for directly
+ * assigning data of a particular type, rather than using the regular
+ * assignment operator (whose implementation simply calls the various set_
+ * methods).
+ */
+ bool is_boolean() const {
+ return is_type(BOOLEAN);
+ }
+ bool& as_boolean_lval() {
+ VERIFY(is_boolean());
+ _dup();
+ return boost::get<bool>(storage->data);
+ }
+ const bool& as_boolean() const {
+ VERIFY(is_boolean());
+ return boost::get<bool>(storage->data);
+ }
+ void set_boolean(const bool val) {
+ set_type(BOOLEAN);
+ storage = val ? true_value : false_value;
+ }
+
+ bool is_datetime() const {
+ return is_type(DATETIME);
+ }
+ datetime_t& as_datetime_lval() {
+ VERIFY(is_datetime());
+ _dup();
+ return boost::get<datetime_t>(storage->data);
+ }
+ const datetime_t& as_datetime() const {
+ VERIFY(is_datetime());
+ return boost::get<datetime_t>(storage->data);
+ }
+ void set_datetime(const datetime_t& val) {
+ set_type(DATETIME);
+ storage->data = val;
+ }
+
+ bool is_date() const {
+ return is_type(DATE);
+ }
+ date_t& as_date_lval() {
+ VERIFY(is_date());
+ _dup();
+ return boost::get<date_t>(storage->data);
+ }
+ const date_t& as_date() const {
+ VERIFY(is_date());
+ return boost::get<date_t>(storage->data);
+ }
+ void set_date(const date_t& val) {
+ set_type(DATE);
+ storage->data = val;
+ }
+
+ bool is_long() const {
+ return is_type(INTEGER);
+ }
+ long& as_long_lval() {
+ VERIFY(is_long());
+ _dup();
+ return boost::get<long>(storage->data);
+ }
+ const long& as_long() const {
+ VERIFY(is_long());
+ return boost::get<long>(storage->data);
+ }
+ void set_long(const long val) {
+ set_type(INTEGER);
+ storage->data = val;
+ }
+
+ bool is_amount() const {
+ return is_type(AMOUNT);
+ }
+ amount_t& as_amount_lval() {
+ VERIFY(is_amount());
+ _dup();
+ return boost::get<amount_t>(storage->data);
+ }
+ const amount_t& as_amount() const {
+ VERIFY(is_amount());
+ return boost::get<amount_t>(storage->data);
+ }
+ void set_amount(const amount_t& val) {
+ VERIFY(val.valid());
+ set_type(AMOUNT);
+ storage->data = val;
+ }
+
+ bool is_balance() const {
+ return is_type(BALANCE);
+ }
+ balance_t& as_balance_lval() {
+ VERIFY(is_balance());
+ _dup();
+ return *boost::get<balance_t *>(storage->data);
+ }
+ const balance_t& as_balance() const {
+ VERIFY(is_balance());
+ return *boost::get<balance_t *>(storage->data);
+ }
+ void set_balance(const balance_t& val) {
+ VERIFY(val.valid());
+ set_type(BALANCE);
+ storage->data = new balance_t(val);
+ }
+
+ bool is_string() const {
+ return is_type(STRING);
+ }
+ string& as_string_lval() {
+ VERIFY(is_string());
+ _dup();
+ return boost::get<string>(storage->data);
+ }
+ const string& as_string() const {
+ VERIFY(is_string());
+ return boost::get<string>(storage->data);
+ }
+ void set_string(const string& val = "") {
+ set_type(STRING);
+ storage->data = val;
+ VERIFY(boost::get<string>(storage->data) == val);
+ }
+ void set_string(const char * val = "") {
+ set_type(STRING);
+ storage->data = string(val);
+ VERIFY(boost::get<string>(storage->data) == val);
+ }
+
+ bool is_mask() const {
+ return is_type(MASK);
+ }
+ mask_t& as_mask_lval() {
+ VERIFY(is_mask());
+ _dup();
+ VERIFY(boost::get<mask_t>(storage->data).valid());
+ return boost::get<mask_t>(storage->data);
+ }
+ const mask_t& as_mask() const {
+ VERIFY(is_mask());
+ VERIFY(boost::get<mask_t>(storage->data).valid());
+ return boost::get<mask_t>(storage->data);
+ }
+ void set_mask(const string& val) {
+ set_type(MASK);
+ storage->data = mask_t(val);
+ }
+ void set_mask(const mask_t& val) {
+ set_type(MASK);
+ storage->data = val;
+ }
+
+ bool is_sequence() const {
+ return is_type(SEQUENCE);
+ }
+ sequence_t& as_sequence_lval() {
+ VERIFY(is_sequence());
+ _dup();
+ return *boost::get<sequence_t *>(storage->data);
+ }
+ const sequence_t& as_sequence() const {
+ VERIFY(is_sequence());
+ return *boost::get<sequence_t *>(storage->data);
+ }
+ void set_sequence(const sequence_t& val) {
+ set_type(SEQUENCE);
+ storage->data = new sequence_t(val);
+ }
+
+ /**
+ * Dealing with scope pointers.
+ */
+ bool is_scope() const {
+ return is_type(SCOPE);
+ }
+ scope_t * as_scope() const {
+ VERIFY(is_scope());
+ return boost::get<scope_t *>(storage->data);
+ }
+ void set_scope(scope_t * val) {
+ set_type(SCOPE);
+ storage->data = val;
+ }
+
+ /**
+ * Data conversion methods. These methods convert a value object to
+ * its underlying type, where possible. If not possible, an
+ * exception is thrown.
+ */
+ bool to_boolean() const;
+ int to_int() const;
+ long to_long() const;
+ datetime_t to_datetime() const;
+ date_t to_date() const;
+ amount_t to_amount() const;
+ balance_t to_balance() const;
+ string to_string() const;
+ mask_t to_mask() const;
+ sequence_t to_sequence() const;
+
+ /**
+ * Dynamic typing conversion methods.
+ *
+ * `cast(type_t)' returns a new value whose type has been cast to
+ * the given type, but whose value is based on the original value.
+ * For example, the uncommoditized AMOUNT "100.00" could be cast to
+ * an INTEGER value. If a cast would lose information or is not
+ * meaningful, an exception is thrown.
+ *
+ * `simplify()' is an automatic cast to the simplest type that can
+ * still represent the original value.
+ *
+ * There are also "in-place" versions of these two methods:
+ * in_place_cast
+ * in_place_simplify
+ */
+ value_t casted(type_t cast_type) const {
+ value_t temp(*this);
+ temp.in_place_cast(cast_type);
+ return temp;
+ }
+ void in_place_cast(type_t cast_type);
+
+ value_t simplified() const {
+ value_t temp = *this;
+ temp.in_place_simplify();
+ return temp;
+ }
+ void in_place_simplify();
+
+ value_t number() const;
+
+ /**
+ * Annotated commodity methods.
+ */
+ void annotate(const annotation_t& details);
+ bool has_annotation() const;
+
+ annotation_t& annotation();
+ const annotation_t& annotation() const {
+ return const_cast<value_t&>(*this).annotation();
+ }
+
+ value_t strip_annotations(const keep_details_t& what_to_keep) const;
+
+ /**
+ * Collection-style access methods for SEQUENCE values.
+ */
+ value_t& operator[](const std::size_t index) {
+ VERIFY(! is_null());
+ if (is_sequence())
+ return as_sequence_lval()[index];
+ else if (index == 0)
+ return *this;
+
+ assert(false);
+ static value_t null;
+ return null;
+ }
+ const value_t& operator[](const std::size_t index) const {
+ VERIFY(! is_null());
+ if (is_sequence())
+ return as_sequence()[index];
+ else if (index == 0)
+ return *this;
+
+ assert(false);
+ static value_t null;
+ return null;
+ }
+
+ void push_front(const value_t& val) {
+ if (is_null())
+ *this = sequence_t();
+ if (! is_sequence())
+ in_place_cast(SEQUENCE);
+ as_sequence_lval().push_front(val);
+ }
+
+ void push_back(const value_t& val) {
+ if (is_null())
+ *this = sequence_t();
+ if (! is_sequence())
+ in_place_cast(SEQUENCE);
+ as_sequence_lval().push_back(val);
+ }
+
+ void pop_back() {
+ VERIFY(! is_null());
+
+ if (! is_sequence()) {
+#if BOOST_VERSION >= 103700
+ storage.reset();
+#else
+ storage = intrusive_ptr<storage_t>();
+#endif
+ } else {
+ as_sequence_lval().pop_back();
+
+ const sequence_t& seq(as_sequence());
+ std::size_t new_size = seq.size();
+ if (new_size == 0) {
+#if BOOST_VERSION >= 103700
+ storage.reset();
+#else
+ storage = intrusive_ptr<storage_t>();
+#endif
+ }
+ else if (new_size == 1) {
+ *this = seq.front();
+ }
+ }
+ }
+
+ sequence_t::iterator begin() {
+ return as_sequence_lval().begin();
+ }
+
+ sequence_t::iterator end() {
+ return as_sequence_lval().end();
+ }
+
+ sequence_t::const_iterator begin() const {
+ return as_sequence().begin();
+ }
+
+ sequence_t::const_iterator end() const {
+ return as_sequence().end();
+ }
+
+ std::size_t size() const {
+ if (is_null())
+ return 0;
+ else if (is_sequence())
+ return as_sequence().size();
+ else
+ return 1;
+ }
+
+ bool empty() const {
+ return size() == 0;
+ }
+
+ /**
+ * Informational methods.
+ */
+ string label(optional<type_t> the_type = none) const {
+ switch (the_type ? *the_type : type()) {
+ case VOID:
+ return _("an uninitialized value");
+ case BOOLEAN:
+ return _("a boolean");
+ case DATETIME:
+ return _("a date/time");
+ case DATE:
+ return _("a date");
+ case INTEGER:
+ return _("an integer");
+ case AMOUNT:
+ return _("an amount");
+ case BALANCE:
+ return _("a balance");
+ case STRING:
+ return _("a string");
+ case MASK:
+ return _("a regexp");
+ case SEQUENCE:
+ return _("a sequence");
+ case SCOPE:
+ return _("a scope");
+ default:
+ assert(false);
+ break;
+ }
+ assert(false);
+ return _("<invalid>");
+ }
+
+ /**
+ * Printing methods.
+ */
+ void print(std::ostream& out,
+ const int first_width = -1,
+ const int latter_width = -1,
+ const bool right_justify = false,
+ const bool colorize = false) const;
+ void dump(std::ostream& out, const bool relaxed = true) const;
+
+ /**
+ * Debugging methods.
+ */
+ bool valid() const;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & true_value;
+ ar & false_value;
+ ar & storage;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+#define NULL_VALUE (value_t())
+
+inline value_t string_value(const string& str = "") {
+ return value_t(str, true);
+}
+
+#define VALUE_OR_ZERO(val) ((val).is_null() ? value_t(0L) : (val))
+#define SIMPLIFIED_VALUE_OR_ZERO(val) \
+ ((val).is_null() ? value_t(0L) : (val).simplified())
+
+inline value_t mask_value(const string& str) {
+ return value_t(mask_t(str));
+}
+
+inline std::ostream& operator<<(std::ostream& out, const value_t& val) {
+ val.print(out);
+ return out;
+}
+
+inline string value_context(const value_t& val) {
+ std::ostringstream buf;
+ val.print(buf, 20, 20, true);
+ return buf.str();
+}
+
+template <typename T>
+inline value_t& add_or_set_value(value_t& lhs, const T& rhs) {
+ if (lhs.is_null())
+ lhs = rhs;
+ else
+ lhs += rhs;
+ return lhs;
+}
+
+struct sort_value_t
+{
+ bool inverted;
+ value_t value;
+
+ sort_value_t() : inverted(false) {}
+};
+
+bool sort_value_is_less_than(const std::list<sort_value_t>& left_values,
+ const std::list<sort_value_t>& right_values);
+
+void to_xml(std::ostream& out, const value_t& value);
+
+} // namespace ledger
+
+#endif // _VALUE_H
diff --git a/src/xact.cc b/src/xact.cc
new file mode 100644
index 00000000..623c5772
--- /dev/null
+++ b/src/xact.cc
@@ -0,0 +1,781 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "journal.h"
+#include "pool.h"
+
+namespace ledger {
+
+xact_base_t::xact_base_t(const xact_base_t& xact_base)
+ : item_t(xact_base), journal(xact_base.journal)
+{
+ TRACE_CTOR(xact_base_t, "copy");
+}
+
+xact_base_t::~xact_base_t()
+{
+ TRACE_DTOR(xact_base_t);
+
+ if (! has_flags(ITEM_TEMP)) {
+ foreach (post_t * post, posts) {
+ // If the posting is a temporary, it will be destructed when the
+ // temporary is.
+ assert(! post->has_flags(ITEM_TEMP));
+ checked_delete(post);
+ }
+ }
+}
+
+void xact_base_t::add_post(post_t * post)
+{
+ // You can add temporary postings to transactions, but not real postings to
+ // temporary transactions.
+ if (! post->has_flags(ITEM_TEMP))
+ assert(! has_flags(ITEM_TEMP));
+
+ posts.push_back(post);
+}
+
+bool xact_base_t::remove_post(post_t * post)
+{
+ posts.remove(post);
+ post->xact = NULL;
+ return true;
+}
+
+bool xact_base_t::has_xdata()
+{
+ foreach (post_t * post, posts)
+ if (post->has_xdata())
+ return true;
+
+ return false;
+}
+
+void xact_base_t::clear_xdata()
+{
+ foreach (post_t * post, posts)
+ if (! post->has_flags(ITEM_TEMP))
+ post->clear_xdata();
+}
+
+value_t xact_base_t::magnitude() const
+{
+ value_t halfbal = 0L;
+ foreach (const post_t * post, posts) {
+ if (post->amount.sign() > 0) {
+ if (post->cost)
+ halfbal += *post->cost;
+ else
+ halfbal += post->amount;
+ }
+ }
+ return halfbal;
+}
+
+bool xact_base_t::finalize()
+{
+ // Scan through and compute the total balance for the xact. This is used
+ // for auto-calculating the value of xacts with no cost, and the per-unit
+ // price of unpriced commodities.
+
+ value_t balance;
+ post_t * null_post = NULL;
+
+ foreach (post_t * post, posts) {
+ if (! post->must_balance())
+ continue;
+
+ amount_t& p(post->cost ? *post->cost : post->amount);
+ if (! p.is_null()) {
+ DEBUG("xact.finalize", "post must balance = " << p.reduced());
+ if (! post->cost && post->amount.has_annotation() &&
+ post->amount.annotation().price) {
+ // If the amount has no cost, but is annotated with a per-unit
+ // price, use the price times the amount as the cost
+ post->cost = (*post->amount.annotation().price *
+ post->amount).unrounded();
+ DEBUG("xact.finalize",
+ "annotation price = " << *post->amount.annotation().price);
+ DEBUG("xact.finalize", "amount = " << post->amount);
+ DEBUG("xact.finalize", "priced cost = " << *post->cost);
+ post->add_flags(POST_COST_CALCULATED);
+ add_or_set_value(balance, post->cost->rounded().reduced());
+ } else {
+ // If the amount was a cost, it very likely has the "keep_precision"
+ // flag set, meaning commodity display precision is ignored when
+ // displaying the amount. We never want this set for the balance,
+ // so we must clear the flag in a temporary to avoid it propagating
+ // into the balance.
+ add_or_set_value(balance, p.keep_precision() ?
+ p.rounded().reduced() : p.reduced());
+ }
+ }
+ else if (null_post) {
+ throw_(std::logic_error,
+ _("Only one posting with null amount allowed per transaction"));
+ }
+ else {
+ null_post = post;
+ }
+ }
+ VERIFY(balance.valid());
+
+#if defined(DEBUG_ON)
+ DEBUG("xact.finalize", "initial balance = " << balance);
+ DEBUG("xact.finalize", "balance is " << balance.label());
+ if (balance.is_balance())
+ DEBUG("xact.finalize", "balance commodity count = "
+ << balance.as_balance().amounts.size());
+#endif
+
+ // If there is only one post, balance against the default account if one has
+ // been set.
+
+ if (journal && journal->bucket && posts.size() == 1 && ! balance.is_null()) {
+ null_post = new post_t(journal->bucket, ITEM_GENERATED);
+ null_post->_state = (*posts.begin())->_state;
+ add_post(null_post);
+ }
+
+ if (null_post != NULL) {
+ // If one post has no value at all, its value will become the inverse of
+ // the rest. If multiple commodities are involved, multiple posts are
+ // generated to balance them all.
+
+ DEBUG("xact.finalize", "there was a null posting");
+
+ if (balance.is_balance()) {
+ bool first = true;
+ const balance_t& bal(balance.as_balance());
+ foreach (const balance_t::amounts_map::value_type& pair, bal.amounts) {
+ if (first) {
+ null_post->amount = pair.second.negated();
+ null_post->add_flags(POST_CALCULATED);
+ first = false;
+ } else {
+ post_t * p = new post_t(null_post->account, pair.second.negated(),
+ ITEM_GENERATED | POST_CALCULATED);
+ p->set_state(null_post->state());
+ add_post(p);
+ }
+ }
+ }
+ else if (balance.is_amount()) {
+ null_post->amount = balance.as_amount().negated();
+ null_post->add_flags(POST_CALCULATED);
+ }
+ else if (balance.is_long()) {
+ null_post->amount = amount_t(- balance.as_long());
+ null_post->add_flags(POST_CALCULATED);
+ }
+ else if (! balance.is_null() && ! balance.is_realzero()) {
+ throw_(balance_error, _("Transaction does not balance"));
+ }
+ balance = NULL_VALUE;
+ }
+ else if (balance.is_balance() &&
+ balance.as_balance().amounts.size() == 2) {
+ // When an xact involves two different commodities (regardless of how
+ // many posts there are) determine the conversion ratio by dividing the
+ // total value of one commodity by the total value of the other. This
+ // establishes the per-unit cost for this post for both commodities.
+
+ DEBUG("xact.finalize", "there were exactly two commodities");
+
+ bool saw_cost = false;
+ post_t * top_post = NULL;
+
+ foreach (post_t * post, posts) {
+ if (! post->amount.is_null()) {
+ if (post->amount.has_annotation())
+ top_post = post;
+ else if (! top_post)
+ top_post = post;
+ }
+
+ if (post->cost && ! post->has_flags(POST_COST_CALCULATED)) {
+ saw_cost = true;
+ break;
+ }
+ }
+
+ if (! saw_cost && top_post) {
+ const balance_t& bal(balance.as_balance());
+
+ DEBUG("xact.finalize", "there were no costs, and a valid top_post");
+
+ balance_t::amounts_map::const_iterator a = bal.amounts.begin();
+
+ const amount_t * x = &(*a++).second;
+ const amount_t * y = &(*a++).second;
+
+ if (x->commodity() != top_post->amount.commodity()) {
+ const amount_t * t = x;
+ x = y;
+ y = t;
+ }
+
+ if (*x && *y) {
+ DEBUG("xact.finalize", "primary amount = " << *x);
+ DEBUG("xact.finalize", "secondary amount = " << *y);
+
+ commodity_t& comm(x->commodity());
+ amount_t per_unit_cost;
+ amount_t total_cost;
+
+ foreach (post_t * post, posts) {
+ if (post != top_post && post->must_balance() &&
+ ! post->amount.is_null() &&
+ post->amount.has_annotation() &&
+ post->amount.annotation().price) {
+ amount_t temp = *post->amount.annotation().price * post->amount;
+ if (total_cost.is_null()) {
+ total_cost = temp;
+ y = &total_cost;
+ } else {
+ total_cost += temp;
+ }
+ DEBUG("xact.finalize", "total_cost = " << total_cost);
+ }
+ }
+ per_unit_cost = (*y / *x).abs().unrounded();
+
+ DEBUG("xact.finalize", "per_unit_cost = " << per_unit_cost);
+
+ foreach (post_t * post, posts) {
+ const amount_t& amt(post->amount);
+
+ if (post->must_balance() && amt.commodity() == comm) {
+ balance -= amt;
+ post->cost = per_unit_cost * amt;
+ post->add_flags(POST_COST_CALCULATED);
+ balance += *post->cost;
+
+ DEBUG("xact.finalize", "set post->cost to = " << *post->cost);
+ }
+ }
+ }
+ }
+ }
+
+ // Now that the post list has its final form, calculate the balance once
+ // more in terms of total cost, accounting for any possible gain/loss
+ // amounts.
+
+ DEBUG("xact.finalize", "resolved balance = " << balance);
+
+ posts_list copy(posts);
+
+ foreach (post_t * post, copy) {
+ if (! post->cost)
+ continue;
+
+ if (post->amount.commodity() == post->cost->commodity())
+ throw_(balance_error,
+ _("A posting's cost must be of a different commodity than its amount"));
+
+ cost_breakdown_t breakdown =
+ commodity_pool_t::current_pool->exchange
+ (post->amount, *post->cost, false,
+ datetime_t(date(), time_duration(0, 0, 0, 0)));
+
+ if (post->amount.has_annotation() &&
+ breakdown.basis_cost.commodity() ==
+ breakdown.final_cost.commodity()) {
+ if (amount_t gain_loss = (breakdown.basis_cost -
+ breakdown.final_cost).rounded()) {
+ DEBUG("xact.finalize", "gain_loss = " << gain_loss);
+
+ add_or_set_value(balance, gain_loss.reduced());
+
+ account_t * account;
+ if (gain_loss.sign() > 0)
+ account = journal->find_account(_("Equity:Capital Gains"));
+ else
+ account = journal->find_account(_("Equity:Capital Losses"));
+
+ post_t * p = new post_t(account, gain_loss, ITEM_GENERATED);
+ p->set_state(post->state());
+ add_post(p);
+ DEBUG("xact.finalize", "added gain_loss, balance = " << balance);
+ }
+ } else {
+ post->amount = breakdown.amount;
+ DEBUG("xact.finalize", "added breakdown, balance = " << balance);
+ }
+ }
+
+ DEBUG("xact.finalize", "final balance = " << balance);
+
+ if (! balance.is_null() && ! balance.is_zero()) {
+ add_error_context(item_context(*this, _("While balancing transaction")));
+ add_error_context(_("Unbalanced remainder is:"));
+ add_error_context(value_context(balance));
+ add_error_context(_("Amount to balance against:"));
+ add_error_context(value_context(magnitude()));
+ throw_(balance_error, _("Transaction does not balance"));
+ }
+
+ // Add a pointer to each posting to their related accounts
+
+ if (dynamic_cast<xact_t *>(this)) {
+ bool all_null = true;
+ bool some_null = false;
+
+ foreach (post_t * post, posts) {
+ if (! post->amount.is_null()) {
+ all_null = false;
+ post->amount.in_place_reduce();
+ } else {
+ some_null = true;
+ }
+
+ post->account->add_post(post);
+
+ post->xdata().add_flags(POST_EXT_VISITED);
+ post->account->xdata().add_flags(ACCOUNT_EXT_VISITED);
+ }
+
+ if (all_null)
+ return false; // ignore this xact completely
+ else if (some_null)
+ throw_(balance_error,
+ _("There cannot be null amounts after balancing a transaction"));
+ }
+
+ VERIFY(valid());
+
+ return true;
+}
+
+bool xact_base_t::verify()
+{
+ // Scan through and compute the total balance for the xact.
+
+ value_t balance;
+
+ foreach (post_t * post, posts) {
+ if (! post->must_balance())
+ continue;
+
+ amount_t& p(post->cost ? *post->cost : post->amount);
+ assert(! p.is_null());
+
+ // If the amount was a cost, it very likely has the "keep_precision" flag
+ // set, meaning commodity display precision is ignored when displaying the
+ // amount. We never want this set for the balance, so we must clear the
+ // flag in a temporary to avoid it propagating into the balance.
+ add_or_set_value(balance, p.keep_precision() ?
+ p.rounded().reduced() : p.reduced());
+ }
+ VERIFY(balance.valid());
+
+ // Now that the post list has its final form, calculate the balance once
+ // more in terms of total cost, accounting for any possible gain/loss
+ // amounts.
+
+ foreach (post_t * post, posts) {
+ if (! post->cost)
+ continue;
+
+ if (post->amount.commodity() == post->cost->commodity())
+ throw_(amount_error,
+ _("A posting's cost must be of a different commodity than its amount"));
+ }
+
+ if (! balance.is_null() && ! balance.is_zero()) {
+ add_error_context(item_context(*this, _("While balancing transaction")));
+ add_error_context(_("Unbalanced remainder is:"));
+ add_error_context(value_context(balance));
+ add_error_context(_("Amount to balance against:"));
+ add_error_context(value_context(magnitude()));
+ throw_(balance_error, _("Transaction does not balance"));
+ }
+
+ VERIFY(valid());
+
+ return true;
+}
+
+xact_t::xact_t(const xact_t& e)
+ : xact_base_t(e), code(e.code), payee(e.payee)
+{
+ TRACE_CTOR(xact_t, "copy");
+}
+
+void xact_t::add_post(post_t * post)
+{
+ post->xact = this;
+ xact_base_t::add_post(post);
+}
+
+string xact_t::idstring() const
+{
+ std::ostringstream buf;
+ buf << format_date(*_date, FMT_WRITTEN);
+ buf << payee;
+ magnitude().number().print(buf);
+ return buf.str();
+}
+
+string xact_t::id() const
+{
+ SHA1 sha;
+ sha.Reset();
+ sha << idstring().c_str();
+ uint_least32_t message_digest[5];
+ sha.Result(message_digest);
+ return to_hex(message_digest, 5);
+}
+
+namespace {
+ value_t get_magnitude(xact_t& xact) {
+ return xact.magnitude();
+ }
+ value_t get_idstring(xact_t& xact) {
+ return string_value(xact.idstring());
+ }
+ value_t get_id(xact_t& xact) {
+ return string_value(xact.id());
+ }
+
+ value_t get_code(xact_t& xact) {
+ if (xact.code)
+ return string_value(*xact.code);
+ else
+ return string_value(empty_string);
+ }
+
+ value_t get_payee(xact_t& xact) {
+ return string_value(xact.payee);
+ }
+
+ template <value_t (*Func)(xact_t&)>
+ value_t get_wrapper(call_scope_t& scope) {
+ return (*Func)(find_scope<xact_t>(scope));
+ }
+}
+
+expr_t::ptr_op_t xact_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
+{
+ if (kind != symbol_t::FUNCTION)
+ return item_t::lookup(kind, name);
+
+ switch (name[0]) {
+ case 'c':
+ if (name == "code")
+ return WRAP_FUNCTOR(get_wrapper<&get_code>);
+ break;
+
+ case 'i':
+ if (name == "id")
+ return WRAP_FUNCTOR(get_wrapper<&get_id>);
+ else if (name == "idstring")
+ return WRAP_FUNCTOR(get_wrapper<&get_idstring>);
+ break;
+
+ case 'm':
+ if (name == "magnitude")
+ return WRAP_FUNCTOR(get_wrapper<&get_magnitude>);
+ break;
+
+ case 'p':
+ if (name[1] == '\0' || name == "payee")
+ return WRAP_FUNCTOR(get_wrapper<&get_payee>);
+ break;
+ }
+
+ return item_t::lookup(kind, name);
+}
+
+bool xact_t::valid() const
+{
+ if (! _date) {
+ DEBUG("ledger.validate", "xact_t: ! _date");
+ return false;
+ }
+
+ foreach (post_t * post, posts)
+ if (post->xact != this || ! post->valid()) {
+ DEBUG("ledger.validate", "xact_t: post not valid");
+ return false;
+ }
+
+ return true;
+}
+
+namespace {
+
+ bool post_pred(expr_t::ptr_op_t op, post_t& post)
+ {
+ switch (op->kind) {
+ case expr_t::op_t::VALUE:
+ return op->as_value().to_boolean();
+ break;
+
+ case expr_t::op_t::O_MATCH:
+ if (op->left()->kind == expr_t::op_t::IDENT &&
+ op->left()->as_ident() == "account" &&
+ op->right()->kind == expr_t::op_t::VALUE &&
+ op->right()->as_value().is_mask())
+ return op->right()->as_value().as_mask()
+ .match(post.reported_account()->fullname());
+ else
+ break;
+
+ case expr_t::op_t::O_NOT:
+ return ! post_pred(op->left(), post);
+
+ case expr_t::op_t::O_AND:
+ return post_pred(op->left(), post) && post_pred(op->right(), post);
+
+ case expr_t::op_t::O_OR:
+ return post_pred(op->left(), post) || post_pred(op->right(), post);
+
+ case expr_t::op_t::O_QUERY:
+ if (post_pred(op->left(), post))
+ return post_pred(op->right()->left(), post);
+ else
+ return post_pred(op->right()->right(), post);
+
+ default:
+ break;
+ }
+
+ throw_(calc_error, _("Unhandled operator"));
+ return false;
+ }
+
+} // unnamed namespace
+
+void auto_xact_t::extend_xact(xact_base_t& xact)
+{
+ posts_list initial_posts(xact.posts.begin(), xact.posts.end());
+
+ try {
+
+ bool needs_further_verification = false;
+
+ foreach (post_t * initial_post, initial_posts) {
+ if (initial_post->has_flags(ITEM_GENERATED))
+ continue;
+
+ bool matches_predicate = false;
+ if (try_quick_match) {
+ try {
+ bool found_memoized_result = false;
+ if (! memoized_results.empty()) {
+ std::map<string, bool>::iterator i =
+ memoized_results.find(initial_post->account->fullname());
+ if (i != memoized_results.end()) {
+ found_memoized_result = true;
+ matches_predicate = (*i).second;
+ }
+ }
+
+ // Since the majority of people who use automated transactions simply
+ // match against account names, try using a *much* faster version of
+ // the predicate evaluator.
+ if (! found_memoized_result) {
+ matches_predicate = post_pred(predicate.get_op(), *initial_post);
+ memoized_results.insert
+ (std::pair<string, bool>(initial_post->account->fullname(),
+ matches_predicate));
+ }
+ }
+ catch (...) {
+ DEBUG("xact.extend.fail",
+ "The quick matcher failed, going back to regular eval");
+ try_quick_match = false;
+ matches_predicate = predicate(*initial_post);
+ }
+ } else {
+ matches_predicate = predicate(*initial_post);
+ }
+ if (matches_predicate) {
+ foreach (post_t * post, posts) {
+ amount_t post_amount;
+ if (post->amount.is_null()) {
+ if (! post->amount_expr)
+ throw_(amount_error,
+ _("Automated transaction's posting has no amount"));
+
+ bind_scope_t bound_scope(*scope_t::default_scope, *initial_post);
+ value_t result(post->amount_expr->calc(bound_scope));
+ if (result.is_long()) {
+ post_amount = result.to_amount();
+ } else {
+ if (! result.is_amount())
+ throw_(amount_error,
+ _("Amount expressions must result in a simple amount"));
+ post_amount = result.as_amount();
+ }
+ } else {
+ post_amount = post->amount;
+ }
+
+ amount_t amt;
+ if (! post_amount.commodity())
+ amt = initial_post->amount * post_amount;
+ else
+ amt = post_amount;
+
+ IF_DEBUG("xact.extend") {
+ DEBUG("xact.extend",
+ "Initial post on line " << initial_post->pos->beg_line << ": "
+ << "amount " << initial_post->amount << " (precision "
+ << initial_post->amount.precision() << ")");
+
+#if defined(DEBUG_ON)
+ if (initial_post->amount.keep_precision())
+ DEBUG("xact.extend", " precision is kept");
+#endif
+
+ DEBUG("xact.extend",
+ "Posting on line " << post->pos->beg_line << ": "
+ << "amount " << post_amount << ", amt " << amt
+ << " (precision " << post_amount.precision()
+ << " != " << amt.precision() << ")");
+
+#if defined(DEBUG_ON)
+ if (post_amount.keep_precision())
+ DEBUG("xact.extend", " precision is kept");
+ if (amt.keep_precision())
+ DEBUG("xact.extend", " amt precision is kept");
+#endif
+ }
+
+ account_t * account = post->account;
+ string fullname = account->fullname();
+ assert(! fullname.empty());
+ if (fullname == "$account" || fullname == "@account")
+ account = initial_post->account;
+
+ // Copy over details so that the resulting post is a mirror of
+ // the automated xact's one.
+ post_t * new_post = new post_t(account, amt);
+ new_post->copy_details(*post);
+ new_post->add_flags(ITEM_GENERATED);
+
+ xact.add_post(new_post);
+ new_post->account->add_post(new_post);
+
+ if (new_post->must_balance())
+ needs_further_verification = true;
+ }
+ }
+ }
+
+ if (needs_further_verification)
+ xact.verify();
+
+ }
+ catch (const std::exception& err) {
+ add_error_context(item_context(*this, _("While applying automated transaction")));
+ add_error_context(item_context(xact, _("While extending transaction")));
+ throw;
+ }
+}
+
+void extend_xact_base(journal_t * journal,
+ xact_base_t& base)
+{
+ foreach (auto_xact_t * xact, journal->auto_xacts)
+ xact->extend_xact(base);
+}
+
+void to_xml(std::ostream& out, const xact_t& xact)
+{
+ push_xml x(out, "transaction", true, true);
+
+ if (xact.state() == item_t::CLEARED)
+ out << " state=\"cleared\"";
+ else if (xact.state() == item_t::PENDING)
+ out << " state=\"pending\"";
+
+ if (xact.has_flags(ITEM_GENERATED))
+ out << " generated=\"true\"";
+
+ x.close_attrs();
+
+ if (xact._date) {
+ push_xml y(out, "date");
+ to_xml(out, *xact._date, false);
+ }
+ if (xact._date_eff) {
+ push_xml y(out, "effective-date");
+ to_xml(out, *xact._date_eff, false);
+ }
+
+ if (xact.code) {
+ push_xml y(out, "code");
+ out << y.guard(*xact.code);
+ }
+
+ {
+ push_xml y(out, "payee");
+ out << y.guard(xact.payee);
+ }
+
+ if (xact.note) {
+ push_xml y(out, "note");
+ out << y.guard(*xact.note);
+ }
+
+ if (xact.metadata) {
+ push_xml y(out, "metadata");
+ foreach (const item_t::string_map::value_type& pair, *xact.metadata) {
+ if (pair.second) {
+ push_xml z(out, "variable");
+ {
+ push_xml w(out, "key");
+ out << y.guard(pair.first);
+ }
+ {
+ push_xml w(out, "value");
+ out << y.guard(*pair.second);
+ }
+ } else {
+ push_xml z(out, "tag");
+ out << y.guard(pair.first);
+ }
+ }
+ }
+}
+
+} // namespace ledger
diff --git a/src/xact.h b/src/xact.h
new file mode 100644
index 00000000..c819b2a0
--- /dev/null
+++ b/src/xact.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup data
+ */
+
+/**
+ * @file xact.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _XACT_H
+#define _XACT_H
+
+#include "item.h"
+#include "predicate.h"
+
+namespace ledger {
+
+class post_t;
+class journal_t;
+
+typedef std::list<post_t *> posts_list;
+
+class xact_base_t : public item_t
+{
+public:
+ journal_t * journal;
+ posts_list posts;
+
+ xact_base_t() : item_t(), journal(NULL) {
+ TRACE_CTOR(xact_base_t, "");
+ }
+ xact_base_t(const xact_base_t& e);
+
+ virtual ~xact_base_t();
+
+ virtual void add_post(post_t * post);
+ virtual bool remove_post(post_t * post);
+
+ posts_list::iterator posts_begin() {
+ return posts.begin();
+ }
+ posts_list::iterator posts_end() {
+ return posts.end();
+ }
+
+ value_t magnitude() const;
+
+ bool finalize();
+ bool verify();
+
+ bool has_xdata();
+ void clear_xdata();
+
+ virtual bool valid() const {
+ return true;
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<item_t>(*this);
+ ar & journal;
+ ar & posts;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class xact_t : public xact_base_t
+{
+public:
+ optional<string> code;
+ string payee;
+
+ xact_t() {
+ TRACE_CTOR(xact_t, "");
+ }
+ xact_t(const xact_t& e);
+
+ virtual ~xact_t() {
+ TRACE_DTOR(xact_t);
+ }
+
+ virtual void add_post(post_t * post);
+
+ string idstring() const;
+ string id() const;
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
+
+ virtual bool valid() const;
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<xact_base_t>(*this);
+ ar & code;
+ ar & payee;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class auto_xact_t : public xact_base_t
+{
+public:
+ predicate_t predicate;
+ bool try_quick_match;
+
+ std::map<string, bool> memoized_results;
+
+ auto_xact_t() : try_quick_match(true) {
+ TRACE_CTOR(auto_xact_t, "");
+ }
+ auto_xact_t(const auto_xact_t& other)
+ : xact_base_t(), predicate(other.predicate),
+ try_quick_match(other.try_quick_match) {
+ TRACE_CTOR(auto_xact_t, "copy");
+ }
+ auto_xact_t(const predicate_t& _predicate)
+ : predicate(_predicate), try_quick_match(true)
+ {
+ TRACE_CTOR(auto_xact_t, "const predicate_t&");
+ }
+
+ virtual ~auto_xact_t() {
+ TRACE_DTOR(auto_xact_t);
+ }
+
+ virtual void extend_xact(xact_base_t& xact);
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<xact_base_t>(*this);
+ ar & predicate;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+class period_xact_t : public xact_base_t
+{
+ public:
+ date_interval_t period;
+ string period_string;
+
+ period_xact_t() {
+ TRACE_CTOR(period_xact_t, "");
+ }
+ period_xact_t(const period_xact_t& e)
+ : xact_base_t(e), period(e.period), period_string(e.period_string) {
+ TRACE_CTOR(period_xact_t, "copy");
+ }
+ period_xact_t(const string& _period)
+ : period(_period), period_string(_period) {
+ TRACE_CTOR(period_xact_t, "const string&");
+ }
+
+ virtual ~period_xact_t() {
+ TRACE_DTOR(period_xact_t);
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<xact_base_t>(*this);
+ ar & period;
+ ar & period_string;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+typedef std::list<xact_t *> xacts_list;
+typedef std::list<auto_xact_t *> auto_xacts_list;
+typedef std::list<period_xact_t *> period_xacts_list;
+
+void to_xml(std::ostream& out, const xact_t& xact);
+
+} // namespace ledger
+
+#endif // _XACT_H
diff --git a/src/xml.cc b/src/xml.cc
new file mode 100644
index 00000000..9cff980a
--- /dev/null
+++ b/src/xml.cc
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+#include <system.hh>
+
+#include "xml.h"
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "session.h"
+#include "report.h"
+
+namespace ledger {
+
+namespace {
+ void xml_account(std::ostream& out, const account_t * acct) {
+ if ((acct->has_xdata() &&
+ acct->xdata().has_flags(ACCOUNT_EXT_VISITED)) ||
+ acct->children_with_flags(ACCOUNT_EXT_VISITED)) {
+ out << "<account id=\"";
+ out.width(sizeof(unsigned long) * 2);
+ out.fill('0');
+ out << std::hex << reinterpret_cast<unsigned long>(acct);
+ out << "\">\n";
+
+ out << "<name>" << acct->name << "</name>\n";
+ value_t total = acct->amount();
+ if (! total.is_null()) {
+ out << "<amount>\n";
+ to_xml(out, total);
+ out << "</amount>\n";
+ }
+ total = acct->total();
+ if (! total.is_null()) {
+ out << "<total>\n";
+ to_xml(out, total);
+ out << "</total>\n";
+ }
+ out << "</account>\n";
+ }
+
+ foreach (const accounts_map::value_type& pair, acct->accounts)
+ xml_account(out, pair.second);
+ }
+
+ void xml_transaction(std::ostream& out, const xact_t * xact) {
+ to_xml(out, *xact);
+
+ foreach (const post_t * post, xact->posts)
+ if (post->has_xdata() &&
+ post->xdata().has_flags(POST_EXT_VISITED))
+ to_xml(out, *post);
+
+ out << "</transaction>\n";
+ }
+}
+
+void format_xml::flush()
+{
+ std::ostream& out(report.output_stream);
+
+ out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+ out << "<ledger version=\"" << VERSION << "\">\n";
+
+ out << "<commodities>\n";
+ foreach (const commodities_pair& pair, commodities) {
+ to_xml(out, *pair.second, true);
+ out << '\n';
+ }
+ out << "</commodities>\n";
+
+ out << "<accounts>\n";
+ xml_account(out, report.session.journal->master);
+ out << "</accounts>\n";
+
+ out << "<transactions>\n";
+ foreach (const xact_t * xact, transactions)
+ xml_transaction(out, xact);
+ out << "</transactions>\n";
+
+ out << "</ledger>\n";
+ out.flush();
+}
+
+void format_xml::operator()(post_t& post)
+{
+ assert(post.xdata().has_flags(POST_EXT_VISITED));
+
+ commodities.insert(commodities_pair(post.amount.commodity().symbol(),
+ &post.amount.commodity()));
+
+ if (transactions_set.find(post.xact) == transactions_set.end())
+ transactions.push_back(post.xact);
+}
+
+} // namespace ledger
diff --git a/src/xml.h b/src/xml.h
new file mode 100644
index 00000000..30a7b1b1
--- /dev/null
+++ b/src/xml.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+ * 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.
+ */
+
+/**
+ * @addtogroup report
+ */
+
+/**
+ * @file xml.h
+ * @author John Wiegley
+ *
+ * @ingroup report
+ *
+ * @brief Brief
+ *
+ * Long.
+ */
+#ifndef _XML_H
+#define _XML_H
+
+#include "chain.h"
+
+namespace ledger {
+
+class xact_t;
+class account_t;
+class commodity_t;
+class post_t;
+class report_t;
+
+/**
+ * @brief Brief
+ *
+ * Long.
+ */
+class format_xml : public item_handler<post_t>
+{
+protected:
+ report_t& report;
+
+ typedef std::map<string, commodity_t *> commodities_map;
+ typedef std::pair<string, commodity_t *> commodities_pair;
+
+ commodities_map commodities;
+ std::set<xact_t *> transactions_set;
+ std::deque<xact_t *> transactions;
+
+public:
+ format_xml(report_t& _report) : report(_report) {
+ TRACE_CTOR(format_xml, "report&");
+ }
+ virtual ~format_xml() {
+ TRACE_DTOR(format_xml);
+ }
+
+ virtual void flush();
+ virtual void operator()(post_t& post);
+};
+
+} // namespace ledger
+
+#endif // _XML_H
diff --git a/startup.cc b/startup.cc
deleted file mode 100644
index 9e35adfb..00000000
--- a/startup.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-#include "ledger.h"
-
-using namespace ledger;
-
-namespace ledger {
- parser_t * binary_parser_ptr = NULL;
- parser_t * xml_parser_ptr = NULL;
- parser_t * gnucash_parser_ptr = NULL;
- parser_t * ofx_parser_ptr = NULL;
- parser_t * qif_parser_ptr = NULL;
- parser_t * textual_parser_ptr = NULL;
-}
-
-namespace {
- binary_parser_t binary_parser;
-#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
- xml_parser_t xml_parser;
- gnucash_parser_t gnucash_parser;
-#endif
-#ifdef HAVE_LIBOFX
- ofx_parser_t ofx_parser;
-#endif
- qif_parser_t qif_parser;
- textual_parser_t textual_parser;
-
- static class startup {
- public:
- startup();
- ~startup();
- } _startup;
-
- startup::startup()
- {
- std::ios::sync_with_stdio(false);
-
- initialize_parser_support();
-
- register_parser(&binary_parser); binary_parser_ptr = &binary_parser;
-#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
- register_parser(&xml_parser); xml_parser_ptr = &xml_parser;
- register_parser(&gnucash_parser); gnucash_parser_ptr = &gnucash_parser;
-#endif
-#ifdef HAVE_LIBOFX
- register_parser(&ofx_parser); ofx_parser_ptr = &ofx_parser;
-#endif
- register_parser(&qif_parser); qif_parser_ptr = &qif_parser;
- register_parser(&textual_parser); textual_parser_ptr = &textual_parser;
- }
-
- startup::~startup()
- {
- if (! ledger::do_cleanup)
- return;
- shutdown_parser_support();
- }
-}
diff --git a/test.py b/test.py
deleted file mode 100755
index 49276de0..00000000
--- a/test.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python
-
-from amounts import *
-
-amt_ncd = Amount("100")
-print amt_ncd
-amt_nc = Amount("100.00")
-print amt_nc
-amt = Amount("$100.00")
-print amt
-namt_ncd = Amount("-100")
-print namt_ncd
-namt_nc = Amount("-100.00")
-print namt_nc
-namt = Amount("$-100.00")
-print namt
-namt2 = Amount("-$100.00")
-print namt2
-
-val = Value("$100.00")
-
-print val
diff --git a/test/ConfirmTests.py b/test/ConfirmTests.py
new file mode 100755
index 00000000..901ae7cd
--- /dev/null
+++ b/test/ConfirmTests.py
@@ -0,0 +1,92 @@
+#!/usr/bin/python
+
+# This script confirms both that the register report "adds up", and that its
+# final balance is the same as what the balance report shows.
+
+import sys
+import os
+import re
+
+from LedgerHarness import LedgerHarness
+
+harness = LedgerHarness(sys.argv)
+tests = sys.argv[3]
+
+if not os.path.isdir(tests) and not os.path.isfile(tests):
+ sys.exit(1)
+
+commands = [
+ "-f '$tests/standard.dat' -O 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728",
+ "-f '$tests/standard.dat' -B c56a21d23a6535184e7152ee138c28974f14280c",
+ "-f '$tests/standard.dat' -V c56a21d23a6535184e7152ee138c28974f14280c",
+ "-f '$tests/standard.dat' -G c56a21d23a6535184e7152ee138c28974f14280c",
+ "-f '$tests/standard.dat' -B c0226fafdf9e6711ac9121cf263e2d50791859cb",
+ "-f '$tests/standard.dat' -V c0226fafdf9e6711ac9121cf263e2d50791859cb",
+ "-f '$tests/standard.dat' -G c0226fafdf9e6711ac9121cf263e2d50791859cb"
+]
+
+def clean(num):
+ num = re.sub("(\s+|\$|,)","", num)
+ m = re.search("([-0-9.]+)", num)
+ if m:
+ return float(m.group(1))
+ else:
+ return float(num)
+
+def confirm_report(command):
+ index = 1
+ last_line = ""
+ failure = False
+ running_total = 0.0
+
+ p = harness.run(re.sub('\$cmd', 'reg', command))
+
+ for line in harness.readlines(p.stdout):
+ match = re.match("\\s*([-$,0-9.]+)\\s+([-$,0-9.]+)", line[54:])
+ if not match:
+ continue
+
+ value = clean(match.group(1))
+ total = clean(match.group(2))
+ running_total += value
+
+ diff = abs(running_total - total)
+ if re.search(' -[VGB] ', command) and diff < 0.015:
+ diff = 0.0
+ if diff > 0.001:
+ print "DISCREPANCY: %.3f (%.3f - %.3f) at line %d:" % \
+ (running_total - total, running_total, total, index)
+ print line,
+ running_total = total
+ failure = True
+
+ index += 1
+ last_line = line
+
+ balance_total = 0.0
+
+ p = harness.run(re.sub('\$cmd', 'bal', command))
+
+ for line in harness.readlines(p.stdout):
+ if line[0] != '-':
+ balance_total = clean(line[:20])
+
+ diff = abs(balance_total - running_total)
+ if re.search(' -[VGB] ', command) and diff < 0.015:
+ diff = 0.0
+ if diff > 0.001:
+ print
+ print "DISCREPANCY: %.3f (%.3f - %.3f) between register and balance" % \
+ (balance_total - running_total, balance_total, running_total)
+ print last_line,
+ failure = True
+
+ return not failure
+
+for cmd in commands:
+ if confirm_report('$ledger $cmd ' + re.sub('\$tests', tests, cmd)):
+ harness.success()
+ else:
+ harness.failure()
+
+harness.exit()
diff --git a/test/DataTests.cc b/test/DataTests.cc
new file mode 100644
index 00000000..8fa1db8a
--- /dev/null
+++ b/test/DataTests.cc
@@ -0,0 +1,3 @@
+#include <cppunit/extensions/HelperMacros.h>
+
+CPPUNIT_REGISTRY_ADD_TO_DEFAULT("data");
diff --git a/test/ExprTests.cc b/test/ExprTests.cc
new file mode 100644
index 00000000..d3f0a734
--- /dev/null
+++ b/test/ExprTests.cc
@@ -0,0 +1,3 @@
+#include <cppunit/extensions/HelperMacros.h>
+
+CPPUNIT_REGISTRY_ADD_TO_DEFAULT("expr");
diff --git a/test/GenerateTests.py b/test/GenerateTests.py
new file mode 100755
index 00000000..d60e0581
--- /dev/null
+++ b/test/GenerateTests.py
@@ -0,0 +1,117 @@
+#!/usr/bin/python
+
+# This script confirms both that the register report "adds up", and that its
+# final balance is the same as what the balance report shows.
+
+import sys
+#import re
+
+from difflib import ndiff
+
+from LedgerHarness import LedgerHarness
+
+harness = LedgerHarness(sys.argv)
+
+#def normalize(line):
+# match = re.match("((\s*)([A-Za-z]+)?(\s*)([-0-9.]+)(\s*)([A-Za-z]+)?)( (.+))?$", line)
+# if match:
+# if match.group(3):
+# prefix = match.group(3) + " " + match.group(5)
+# if match.group(8):
+# return prefix + match.group(8)
+# return prefix
+# elif match.group(7):
+# prefix = match.group(7) + " " + match.group(5)
+# if match.group(8):
+# return prefix + match.group(8)
+# return prefix
+# return line
+
+def generation_test(seed):
+ p_gen = harness.run('$ledger --seed=%d generate' % seed)
+
+ cout = harness.read(p_gen.stdout)
+
+ if not harness.wait(p_gen, msg=("Generation for seed %d failed:" % seed)):
+ return False
+
+ p_print = harness.run('$ledger --actual -f - print')
+ p_print.stdin.write(cout)
+ p_print.stdin.close()
+ p_print_out = p_print.stdout.read()
+
+ if not harness.wait(p_print, msg=("Print for seed %d failed:" % seed)):
+ return False
+
+ #p_cerr_bal = Popen("%s --args-only -f - bal" % ledger, shell=True,
+ # stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
+ #p_cerr_bal.stdin.write(cerr)
+ #p_cerr_bal.stdin.close()
+ #
+ #cerr_lines = [normalize(line) for line in p_cerr_bal.stdout.readlines()]
+ #
+ #if p_cerr_bal.wait() != 0:
+ # print "Stderr balance for seed %d failed due to error:" % seed
+ # print p_cerr_bal.stderr.read()
+ # del p_cerr_bal
+ # return False
+ #del p_cerr_bal
+
+ p_cout_bal = harness.run('$ledger -f - bal')
+ p_cout_bal.stdin.write(cout)
+ p_cout_bal.stdin.close()
+
+ cout_lines = harness.readlines(p_cout_bal.stdout)
+ #norm_cout_lines = [normalize(line) for line in cout_lines]
+
+ if not harness.wait(p_cout_bal, msg=("Stdout balance for seed %d failed:" % seed)):
+ return False
+
+ p_print_bal = harness.run('$ledger -f - bal')
+ p_print_bal.stdin.write(p_print_out)
+ p_print_bal.stdin.close()
+
+ print_lines = harness.readlines(p_print_bal.stdout)
+
+ if not harness.wait(p_print_bal, msg=("Print balance for seed %d failed:" % seed)):
+ return False
+
+ success = True
+ #printed = False
+ #for line in ndiff(cerr_lines, norm_cout_lines, charjunk=None):
+ # if line[:2] == " ":
+ # continue
+ # if not printed:
+ # if success: print
+ # print "Generation failure in output from seed %d (cerr vs. cout):" % seed
+ # if success: failed += 1
+ # success = False
+ # printed = True
+ # print " ", line
+
+ printed = False
+ for line in ndiff(cout_lines, print_lines, charjunk=None):
+ if line[:2] == " ":
+ continue
+ if not printed:
+ if success: print
+ print "Generation failure in output from seed %d (cout vs. print):" % seed
+ success = False
+ printed = True
+ print " ", line
+
+ return success
+
+beg_range = 1
+end_range = 20
+if len(sys.argv) > 4:
+ beg_range = int(sys.argv[3])
+ end_range = int(sys.argv[4])
+
+for i in range(beg_range, end_range):
+ if generation_test(i):
+ harness.success()
+ else:
+ harness.failure()
+
+harness.exit()
diff --git a/test/LedgerHarness.py b/test/LedgerHarness.py
new file mode 100755
index 00000000..8a5af123
--- /dev/null
+++ b/test/LedgerHarness.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import re
+
+from subprocess import Popen, PIPE
+
+class LedgerHarness:
+ ledger = None
+ sourcepath = None
+ succeeded = 0
+ failed = 0
+ verify = False
+ gmalloc = False
+
+ def __init__(self, argv):
+ if not os.path.isfile(argv[1]):
+ print "Cannot find ledger at '%s'" % argv[1]
+ sys.exit(1)
+ if not os.path.isdir(argv[2]):
+ print "Cannot find source path at '%s'" % argv[2]
+ sys.exit(1)
+
+ self.ledger = argv[1]
+ self.sourcepath = argv[2]
+ self.succeeded = 0
+ self.failed = 0
+ self.verify = '--verify' in argv
+ self.gmalloc = '--gmalloc' in argv
+
+ def run(self, command, verify=None, gmalloc=None, columns=True):
+ env = os.environ.copy()
+
+ if (gmalloc is not None and gmalloc) or \
+ (gmalloc is None and self.gmalloc):
+ env['MallocGuardEdges'] = '1'
+ env['MallocScribble'] = '1'
+ env['MallocPreScribble'] = '1'
+ env['MallocCheckHeapStart'] = '1000'
+ env['MallocCheckHeapEach'] = '10000'
+ env['DYLD_INSERT_LIBRARIES'] = '/usr/lib/libgmalloc.dylib'
+ env['MALLOC_PROTECT_BEFORE'] = '1'
+ env['MALLOC_FILL_SPACE'] = '1'
+ env['MALLOC_STRICT_SIZE'] = '1'
+
+ if (verify is not None and verify) or \
+ (verify is None and self.verify):
+ insert = ' --verify'
+ else:
+ insert = ''
+
+ if columns:
+ insert += ' --columns=80'
+
+ command = re.sub('\$ledger', '%s%s %s' % \
+ (self.ledger, insert, '--args-only'), command)
+
+ return Popen(command, shell=True, close_fds=True, env=env,
+ stdin=PIPE, stdout=PIPE, stderr=PIPE)
+
+ def read(self, fd):
+ text = ""
+ text_data = os.read(fd.fileno(), 8192)
+ while text_data:
+ if text_data:
+ text += text_data
+ text_data = os.read(fd.fileno(), 8192)
+ if text_data:
+ text += text_data
+ return text
+
+ def readlines(self, fd):
+ lines = []
+ for line in fd.readlines():
+ if line == "GuardMalloc: Allocations will be placed on byte boundaries.\n" or \
+ line == "GuardMalloc: - Some buffer overruns may not be noticed.\n" or \
+ line == "GuardMalloc: - Applications using vector instructions (e.g., SSE or Altivec) may fail.\n" or \
+ line == "GuardMalloc: - Applications expecting word-aligned pointers may fail (such as Carbon applications)\n" or \
+ line == "GuardMalloc: GuardMalloc version 18\n":
+ continue
+ else:
+ lines.append(line)
+ return lines
+
+ def wait(self, process, msg='Ledger invocation failed:'):
+ if process.wait() != 0:
+ print msg
+ print process.stderr.read()
+ self.failure()
+ return False
+ return True
+
+ def success(self):
+ sys.stdout.write(".")
+ self.succeeded += 1
+
+ def failure(self):
+ sys.stdout.write("E")
+ self.failed += 1
+
+ def exit(self):
+ print
+ if self.succeeded > 0:
+ print "OK (%d) " % self.succeeded,
+ if self.failed > 0:
+ print "FAILED (%d)" % self.failed,
+ print
+
+ sys.exit(self.failed)
+
+if __name__ == '__main__':
+ harness = LedgerHarness(sys.argv)
+ proc = harness.run('$ledger -f doc/sample.dat reg')
+ print 'STDOUT:'
+ print proc.stdout.read()
+ print 'STDERR:'
+ print proc.stderr.read()
+ harness.success()
+ harness.exit()
diff --git a/test/MathTests.cc b/test/MathTests.cc
new file mode 100644
index 00000000..c1e8c839
--- /dev/null
+++ b/test/MathTests.cc
@@ -0,0 +1,3 @@
+#include <cppunit/extensions/HelperMacros.h>
+
+CPPUNIT_REGISTRY_ADD_TO_DEFAULT("math");
diff --git a/test/PyUnitTests.py b/test/PyUnitTests.py
new file mode 100755
index 00000000..a77d99ad
--- /dev/null
+++ b/test/PyUnitTests.py
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+PYTHONPATH="%builddir%/.libs":$PYTHONPATH \
+LD_LIBRARY_PATH="%builddir%/.libs":$LD_LIBRARY_PATH \
+DYLD_LIBRARY_PATH="%builddir%/.libs":$DYLD_LIBRARY_PATH \
+ %python% "%builddir%"/test/python/UnitTests.py
diff --git a/test/RegressTests.py b/test/RegressTests.py
new file mode 100755
index 00000000..13a0a113
--- /dev/null
+++ b/test/RegressTests.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import re
+import tempfile
+
+from string import join
+from difflib import unified_diff
+
+from LedgerHarness import LedgerHarness
+
+harness = LedgerHarness(sys.argv)
+tests = sys.argv[3]
+
+if not os.path.isdir(tests) and not os.path.isfile(tests):
+ sys.exit(1)
+
+class RegressFile:
+ def __init__(self, filename):
+ self.filename = filename
+ self.fd = open(self.filename)
+
+ def is_directive(self, line):
+ return line == "<<<\n" or \
+ line == ">>>1\n" or \
+ line == ">>>2\n" or \
+ line.startswith("===")
+
+ def transform_line(self, line):
+ line = re.sub('\$sourcepath', harness.sourcepath, line)
+ return line
+
+ def read_section(self):
+ lines = []
+ line = self.fd.readline()
+ while not self.is_directive(line):
+ lines.append(self.transform_line(line))
+ line = self.fd.readline()
+ return (lines, line)
+
+ def read_test(self, last_test = None):
+ test = {
+ 'command': None,
+ 'input': None,
+ 'output': None,
+ 'error': None,
+ 'exitcode': None
+ }
+ if last_test:
+ test['input'] = last_test['input']
+
+ line = self.fd.readline()
+ while line:
+ if line == "<<<\n":
+ (test['input'], line) = self.read_section()
+ elif line == ">>>1\n":
+ (test['output'], line) = self.read_section()
+ elif line == ">>>2\n":
+ (test['error'], line) = self.read_section()
+ elif line.startswith("==="):
+ match = re.match('=== ([0-9]+)', line)
+ assert match
+ test['exitcode'] = int(match.group(1))
+ return test
+ else:
+ test['command'] = self.transform_line(line)
+ line = self.fd.readline()
+
+ return None
+
+ def run_test(self, test):
+ use_stdin = False
+ if test['command'].find("-f - ") != -1:
+ use_stdin = True
+
+ test['command'] = '$ledger ' + test['command']
+ else:
+ tempdata = tempfile.mkstemp()
+
+ os.write(tempdata[0], join(test['input'], ''))
+ os.close(tempdata[0])
+
+ test['command'] = (('$ledger -f "%s" ' % tempdata[1]) +
+ test['command'])
+
+ p = harness.run(test['command'],
+ columns=(not re.search('--columns', test['command'])))
+
+ if use_stdin:
+ p.stdin.write(join(test['input'], ''))
+ p.stdin.close()
+
+ success = True
+ printed = False
+ index = 0
+ for line in unified_diff(test['output'], harness.readlines(p.stdout)):
+ index += 1
+ if index < 3:
+ continue
+ if not printed:
+ if success: print
+ print "Regression failure in output from %s:" % \
+ os.path.basename(self.filename)
+ success = False
+ printed = True
+ print " ", line,
+
+ printed = False
+ index = 0
+ for line in unified_diff([re.sub('\$FILE', tempdata[1], line)
+ for line in test['error']],
+ harness.readlines(p.stderr)):
+ index += 1
+ if index < 3:
+ continue
+ if not printed:
+ if success: print
+ print "Regression failure in error output from %s:" % \
+ os.path.basename(self.filename)
+ success = False
+ printed = True
+ print " ", line,
+
+ if test['exitcode'] == p.wait():
+ if success:
+ harness.success()
+ else:
+ harness.failure()
+ else:
+ if success: print
+ print "Regression failure in exitcode from %s: %d (expected) != %d" % \
+ (os.path.basename(self.filename), test['exitcode'], p.returncode)
+ harness.failure()
+
+ if not use_stdin:
+ os.remove(tempdata[1])
+
+ def run_tests(self):
+ test = self.read_test()
+ while test:
+ self.run_test(test)
+ test = self.read_test(test)
+
+ def close(self):
+ self.fd.close()
+
+if os.path.isdir(tests):
+ for test_file in os.listdir(tests):
+ if re.search('\.test$', test_file):
+ entry = RegressFile(os.path.join(tests, test_file))
+ entry.run_tests()
+ entry.close()
+else:
+ entry = RegressFile(tests)
+ entry.run_tests()
+ entry.close()
+
+harness.exit()
diff --git a/test/ReportTests.cc b/test/ReportTests.cc
new file mode 100644
index 00000000..2fabbe9a
--- /dev/null
+++ b/test/ReportTests.cc
@@ -0,0 +1,3 @@
+#include <cppunit/extensions/HelperMacros.h>
+
+CPPUNIT_REGISTRY_ADD_TO_DEFAULT("report");
diff --git a/test/UnitTests.cc b/test/UnitTests.cc
new file mode 100644
index 00000000..2c5c0406
--- /dev/null
+++ b/test/UnitTests.cc
@@ -0,0 +1,116 @@
+#include <system.hh>
+
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/TestRunner.h>
+#include <cppunit/TextTestProgressListener.h>
+#include <cppunit/BriefTestProgressListener.h>
+#include <cppunit/XmlOutputter.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "UnitTests.h"
+
+#include "utils.h"
+
+// Create the CppUnit registry
+
+CPPUNIT_REGISTRY_ADD_TO_DEFAULT("Framework");
+
+// Create a sample test, which acts both as a template, and a
+// verification that the basic framework is functioning.
+
+class UnitTests : public CPPUNIT_NS::TestCase
+{
+ CPPUNIT_TEST_SUITE( UnitTests );
+ CPPUNIT_TEST( testInitialization );
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ UnitTests() {}
+ virtual ~UnitTests() {}
+
+ virtual void setUp() {}
+ virtual void tearDown() {}
+
+ void testInitialization() {
+ assertEqual(std::string("Hello, world!"),
+ std::string("Hello, world!"));
+ }
+
+private:
+ UnitTests( const UnitTests &copy );
+ void operator =( const UnitTests &copy );
+};
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(UnitTests, "framework");
+
+// Create the various runners and commence running the tests!
+
+int main(int argc, char* argv[])
+{
+ int index = 1;
+
+ if (argc > index && std::string(argv[index]) == "--verify") {
+#if defined(VERIFY_ON)
+ ledger::verify_enabled = true;
+#endif
+ index++;
+ }
+
+ // Retreive test path from command line first argument. Default to
+ // "" which resolves to the top level suite.
+ std::string testPath = ((argc > index) ? std::string(argv[index]) :
+ std::string(""));
+
+ // Create the event manager and test controller
+ CPPUNIT_NS::TestResult controller;
+
+ // Add a listener that collects test results
+ CPPUNIT_NS::TestResultCollector result;
+ controller.addListener(&result);
+
+ // Add a listener that print dots as test run.
+#if 1
+ CPPUNIT_NS::TextTestProgressListener progress;
+#else
+ CPPUNIT_NS::BriefTestProgressListener progress;
+#endif
+ controller.addListener(&progress);
+
+ // Add the top suite to the test runner
+ CPPUNIT_NS::TestRunner runner;
+ runner.addTest(CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest());
+ try {
+#if defined(VERIFY_ON)
+ IF_VERIFY()
+ ledger::initialize_memory_tracing();
+#endif
+
+ runner.run(controller, testPath);
+
+#if defined(VERIFY_ON)
+ IF_VERIFY()
+ ledger::shutdown_memory_tracing();
+#endif
+
+#if 1
+ // Print test in a compiler compatible format.
+ CPPUNIT_NS::CompilerOutputter outputter(&result, CPPUNIT_NS::stdCOut());
+ outputter.write();
+#else
+ // Uncomment this for XML output
+ std::ofstream file("tests.xml");
+ CPPUNIT_NS::XmlOutputter xml(&result, file);
+ xml.setStyleSheet("report.xsl");
+ xml.write();
+ file.close();
+#endif
+ }
+ catch (std::invalid_argument &e) { // Test path not resolved
+ CPPUNIT_NS::stdCOut() << "\nERROR: " << e.what() << "\n";
+ return 0;
+ }
+
+ return result.wasSuccessful() ? 0 : 1;
+}
diff --git a/test/UnitTests.h b/test/UnitTests.h
new file mode 100644
index 00000000..d9314ddf
--- /dev/null
+++ b/test/UnitTests.h
@@ -0,0 +1,20 @@
+#ifndef _UNITTESTS_H
+#define _UNITTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/Exception.h>
+#include <cppunit/Portability.h>
+
+#define assertDoublesEqual(x,y,z,w) CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(x,y,z,w)
+#define assertEqual(x,y) CPPUNIT_ASSERT_EQUAL(x,y)
+#define assertNotEqual(x,y) CPPUNIT_ASSERT((x) != (y))
+#define assertTrue(x) CPPUNIT_ASSERT(x)
+#define assertFalse(x) CPPUNIT_ASSERT(! (x))
+#define assertValid(x) CPPUNIT_ASSERT((x).valid())
+#define assertEqualMessage(x,y,z) CPPUNIT_ASSERT_EQUAL_MESSAGE(x,y,z)
+#define assertMessage(x,y) CPPUNIT_ASSERT_MESSAGE(x,y)
+#define assertThrow(x,y) CPPUNIT_ASSERT_THROW(x,y)
+
+#define internalAmount(x) amount_t::exact(x)
+
+#endif /* _UNITTESTS_H */
diff --git a/test/UtilTests.cc b/test/UtilTests.cc
new file mode 100644
index 00000000..f584db89
--- /dev/null
+++ b/test/UtilTests.cc
@@ -0,0 +1,3 @@
+#include <cppunit/extensions/HelperMacros.h>
+
+CPPUNIT_REGISTRY_ADD_TO_DEFAULT("util");
diff --git a/test/baseline/feat-balance-assignments.test b/test/baseline/feat-balance-assignments.test
new file mode 100644
index 00000000..74fe9ddb
--- /dev/null
+++ b/test/baseline/feat-balance-assignments.test
@@ -0,0 +1,37 @@
+bal
+<<<
+2009/01/01 Entry
+ Assets:Cash $10,000.00
+ Equity:Opening Balances
+
+2009/02/01 Entry
+ Expenses:Cash $100.00
+ Assets:Cash
+
+2009/02/02 Entry
+ Expenses:Cash $100.00
+ Assets:Cash
+
+2009/02/03 Entry
+ Expenses:Cash $100.00
+ Assets:Cash $-100.00 = $9,700.00
+
+2009/02/04 Entry
+ Expenses:Cash $100.00
+ Assets:Cash $-100.00 = $9,600.00
+
+2009/02/05 Entry
+ Expenses:Cash $100.00
+ Assets:Cash
+
+2009/02/05 Entry
+ Expenses:Cash
+ Assets:Cash = ($4,000.00 + $100.00)
+>>>1
+ $4,100.00 Assets:Cash
+ $-10,000.00 Equity:Opening Balances
+ $5,900.00 Expenses:Cash
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/baseline/feat-fixated-prices.test b/test/baseline/feat-fixated-prices.test
new file mode 100644
index 00000000..11330dea
--- /dev/null
+++ b/test/baseline/feat-fixated-prices.test
@@ -0,0 +1,24 @@
+reg -V gas
+<<<
+1990/01/01 Payee
+ Expenses:Gas 100 GAL {=$2}
+ Liabilities:MasterCard $-200
+
+P 1990/01/15 12:00:00 GAL $3
+
+1990/02/01 Payee
+ Expenses:Gas 100 FOO {$2}
+ Liabilities:MasterCard $-200
+
+P 1990/02/15 12:00:00 FOO $3
+
+1990/02/20 Payee
+ Expenses:Gas 100 FOO
+ Liabilities:MasterCard
+>>>1
+90-Jan-01 Payee Expenses:Gas $200 $200
+90-Feb-01 Payee Expenses:Gas $200 $400
+90-Feb-20 Commodities revalued <Revalued> $100 $500
+90-Feb-20 Payee Expenses:Gas $300 $800
+>>>2
+=== 0
diff --git a/test/baseline/opt-abbrev-len.test b/test/baseline/opt-abbrev-len.test
new file mode 100644
index 00000000..40313b22
--- /dev/null
+++ b/test/baseline/opt-abbrev-len.test
@@ -0,0 +1,11 @@
+reg --abbrev-len=4
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX Asse:Inve:Vang:VMMXX 0.350 VMMXX 0.350 VMMXX
+ Inco:Divi:Vang:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-account-width.test b/test/baseline/opt-account-width.test
new file mode 100644
index 00000000..b0493e87
--- /dev/null
+++ b/test/baseline/opt-account-width.test
@@ -0,0 +1,11 @@
+reg --account-width=40
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX Assets:Investments:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ Income:Dividends:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-account.test b/test/baseline/opt-account.test
new file mode 100644
index 00000000..7cda3c4d
--- /dev/null
+++ b/test/baseline/opt-account.test
@@ -0,0 +1,11 @@
+reg --account='payee + ":" + commodity'
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX RD VMMXX:VMMXX 0.350 VMMXX 0.350 VMMXX
+07-Feb-02 RD VMMXX RD VMMXX:$ $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-actual.test b/test/baseline/opt-actual.test
new file mode 100644
index 00000000..8e7b432e
--- /dev/null
+++ b/test/baseline/opt-actual.test
@@ -0,0 +1,15 @@
+print --actual
+<<<
+= Books
+ Expenses:Taxes 0.05
+ Assets:Checking -0.05
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash $-10.00
+>>>1
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash $-10.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-add-budget.test b/test/baseline/opt-add-budget.test
new file mode 100644
index 00000000..535335d3
--- /dev/null
+++ b/test/baseline/opt-add-budget.test
@@ -0,0 +1,368 @@
+reg --add-budget books cards
+<<<
+~ monthly
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 Budget transaction Expenses:Books $-10.00 $-10.00
+08-Jan-01 January Expenses:Books $10.00 0
+ Liabilities:Cards $10.00 $10.00
+08-Jan-31 End of January Expenses:Books $10.00 $20.00
+ Liabilities:Cards $10.00 $30.00
+08-Feb-01 Budget transaction Expenses:Books $-10.00 $20.00
+08-Feb-01 February Expenses:Books $20.00 $40.00
+ Liabilities:Cards $20.00 $60.00
+08-Feb-28 End of February Expenses:Books $20.00 $80.00
+ Liabilities:Cards $20.00 $100.00
+08-Mar-01 Budget transaction Expenses:Books $-10.00 $90.00
+08-Mar-01 March Expenses:Books $30.00 $120.00
+ Liabilities:Cards $30.00 $150.00
+08-Mar-31 End of March Expenses:Books $30.00 $180.00
+ Liabilities:Cards $30.00 $210.00
+08-Apr-01 Budget transaction Expenses:Books $-10.00 $200.00
+08-Apr-01 April Expenses:Books $40.00 $240.00
+ Liabilities:Cards $40.00 $280.00
+08-Apr-30 End of April Expenses:Books $40.00 $320.00
+ Liabilities:Cards $40.00 $360.00
+08-May-01 Budget transaction Expenses:Books $-10.00 $350.00
+08-May-01 May Expenses:Books $50.00 $400.00
+ Liabilities:Cards $50.00 $450.00
+08-May-31 End of May Expenses:Books $50.00 $500.00
+ Liabilities:Cards $50.00 $550.00
+08-Jun-01 Budget transaction Expenses:Books $-10.00 $540.00
+08-Jun-01 June Expenses:Books $60.00 $600.00
+ Liabilities:Cards $60.00 $660.00
+08-Jun-30 End of June Expenses:Books $60.00 $720.00
+ Liabilities:Cards $60.00 $780.00
+08-Jul-01 Budget transaction Expenses:Books $-10.00 $770.00
+08-Jul-01 July Expenses:Books $70.00 $840.00
+ Liabilities:Cards $70.00 $910.00
+08-Jul-31 End of July Expenses:Books $70.00 $980.00
+ Liabilities:Cards $70.00 $1050.00
+08-Aug-01 Budget transaction Expenses:Books $-10.00 $1040.00
+08-Aug-01 August Expenses:Books $80.00 $1120.00
+ Liabilities:Cards $80.00 $1200.00
+08-Aug-31 End of August Expenses:Books $80.00 $1280.00
+ Liabilities:Cards $80.00 $1360.00
+08-Sep-01 Budget transaction Expenses:Books $-10.00 $1350.00
+08-Sep-01 September Expenses:Books $90.00 $1440.00
+ Liabilities:Cards $90.00 $1530.00
+08-Sep-30 End of September Expenses:Books $90.00 $1620.00
+ Liabilities:Cards $90.00 $1710.00
+08-Oct-01 Budget transaction Expenses:Books $-10.00 $1700.00
+08-Oct-01 October Expenses:Books $100.00 $1800.00
+ Liabilities:Cards $100.00 $1900.00
+08-Oct-31 End of October Expenses:Books $100.00 $2000.00
+ Liabilities:Cards $100.00 $2100.00
+08-Nov-01 Budget transaction Expenses:Books $-10.00 $2090.00
+08-Nov-01 November Expenses:Books $110.00 $2200.00
+ Liabilities:Cards $110.00 $2310.00
+08-Nov-30 End of November Expenses:Books $110.00 $2420.00
+ Liabilities:Cards $110.00 $2530.00
+08-Dec-01 Budget transaction Expenses:Books $-10.00 $2520.00
+08-Dec-01 December Expenses:Books $120.00 $2640.00
+ Liabilities:Cards $120.00 $2760.00
+08-Dec-31 End of December Expenses:Books $120.00 $2880.00
+ Liabilities:Cards $120.00 $3000.00
+09-Jan-01 Budget transaction Expenses:Books $-10.00 $2990.00
+09-Jan-01 January Expenses:Books $10.00 $3000.00
+ Liabilities:Cards $10.00 $3010.00
+09-Jan-31 End of January Expenses:Books $10.00 $3020.00
+ Liabilities:Cards $10.00 $3030.00
+09-Feb-01 Budget transaction Expenses:Books $-10.00 $3020.00
+09-Feb-01 February Expenses:Books $20.00 $3040.00
+ Liabilities:Cards $20.00 $3060.00
+09-Feb-28 End of February Expenses:Books $20.00 $3080.00
+ Liabilities:Cards $20.00 $3100.00
+09-Mar-01 Budget transaction Expenses:Books $-10.00 $3090.00
+09-Mar-01 March Expenses:Books $30.00 $3120.00
+ Liabilities:Cards $30.00 $3150.00
+09-Mar-31 End of March Expenses:Books $30.00 $3180.00
+ Liabilities:Cards $30.00 $3210.00
+09-Apr-01 Budget transaction Expenses:Books $-10.00 $3200.00
+09-Apr-01 April Expenses:Books $40.00 $3240.00
+ Liabilities:Cards $40.00 $3280.00
+09-Apr-30 End of April Expenses:Books $40.00 $3320.00
+ Liabilities:Cards $40.00 $3360.00
+09-May-01 Budget transaction Expenses:Books $-10.00 $3350.00
+09-May-01 May Expenses:Books $50.00 $3400.00
+ Liabilities:Cards $50.00 $3450.00
+09-May-31 End of May Expenses:Books $50.00 $3500.00
+ Liabilities:Cards $50.00 $3550.00
+09-Jun-01 Budget transaction Expenses:Books $-10.00 $3540.00
+09-Jun-01 June Expenses:Books $60.00 $3600.00
+ Liabilities:Cards $60.00 $3660.00
+09-Jun-30 End of June Expenses:Books $60.00 $3720.00
+ Liabilities:Cards $60.00 $3780.00
+09-Jul-01 Budget transaction Expenses:Books $-10.00 $3770.00
+09-Jul-01 July Expenses:Books $70.00 $3840.00
+ Liabilities:Cards $70.00 $3910.00
+09-Jul-31 End of July Expenses:Books $70.00 $3980.00
+ Liabilities:Cards $70.00 $4050.00
+09-Aug-01 Budget transaction Expenses:Books $-10.00 $4040.00
+09-Aug-01 August Expenses:Books $80.00 $4120.00
+ Liabilities:Cards $80.00 $4200.00
+09-Aug-31 End of August Expenses:Books $80.00 $4280.00
+ Liabilities:Cards $80.00 $4360.00
+09-Sep-01 Budget transaction Expenses:Books $-10.00 $4350.00
+09-Sep-01 September Expenses:Books $90.00 $4440.00
+ Liabilities:Cards $90.00 $4530.00
+09-Sep-30 End of September Expenses:Books $90.00 $4620.00
+ Liabilities:Cards $90.00 $4710.00
+09-Oct-01 Budget transaction Expenses:Books $-10.00 $4700.00
+09-Oct-01 October Expenses:Books $100.00 $4800.00
+ Liabilities:Cards $100.00 $4900.00
+09-Oct-31 End of October Expenses:Books $100.00 $5000.00
+ Liabilities:Cards $100.00 $5100.00
+09-Nov-01 Budget transaction Expenses:Books $-10.00 $5090.00
+09-Nov-01 November Expenses:Books $110.00 $5200.00
+ Liabilities:Cards $110.00 $5310.00
+09-Nov-30 End of November Expenses:Books $110.00 $5420.00
+ Liabilities:Cards $110.00 $5530.00
+09-Dec-01 Budget transaction Expenses:Books $-10.00 $5520.00
+09-Dec-01 December Expenses:Books $120.00 $5640.00
+ Liabilities:Cards $120.00 $5760.00
+09-Dec-31 End of December Expenses:Books $120.00 $5880.00
+ Liabilities:Cards $120.00 $6000.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-amount-data.test b/test/baseline/opt-amount-data.test
new file mode 100644
index 00000000..7b88c9f3
--- /dev/null
+++ b/test/baseline/opt-amount-data.test
@@ -0,0 +1,10 @@
+reg --amount-data
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+2007-02-02 0.35
+2007-02-02 -0.35
+>>>2
+=== 0
diff --git a/test/baseline/opt-amount-width.test b/test/baseline/opt-amount-width.test
new file mode 100644
index 00000000..32282214
--- /dev/null
+++ b/test/baseline/opt-amount-width.test
@@ -0,0 +1,11 @@
+reg --amount-width=18
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-amount.test b/test/baseline/opt-amount.test
new file mode 100644
index 00000000..2ebbf055
--- /dev/null
+++ b/test/baseline/opt-amount.test
@@ -0,0 +1,10 @@
+reg --amount=10
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX 10 10
+ In:Di:Vanguard:VMMXX 10 20
+>>>2
+=== 0
diff --git a/test/baseline/opt-anon.test b/test/baseline/opt-anon.test
new file mode 100644
index 00000000..6fe6b75f
--- /dev/null
+++ b/test/baseline/opt-anon.test
@@ -0,0 +1,11 @@
+reg --anon
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 6a93dcb3 da:20:5d:27:988a9c3a 0.350 VMMXX 0.350 VMMXX
+ da:1c:b6:27:988a9c3a $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-average.test b/test/baseline/opt-average.test
new file mode 100644
index 00000000..82de294d
--- /dev/null
+++ b/test/baseline/opt-average.test
@@ -0,0 +1,244 @@
+reg --average books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Expenses:Books $10.00 $10.00
+08-Jan-31 End of January Expenses:Books $10.00 $10.00
+08-Feb-01 February Expenses:Books $20.00 $13.33
+08-Feb-28 End of February Expenses:Books $20.00 $15.00
+08-Mar-01 March Expenses:Books $30.00 $18.00
+08-Mar-31 End of March Expenses:Books $30.00 $20.00
+08-Apr-01 April Expenses:Books $40.00 $22.86
+08-Apr-30 End of April Expenses:Books $40.00 $25.00
+08-May-01 May Expenses:Books $50.00 $27.78
+08-May-31 End of May Expenses:Books $50.00 $30.00
+08-Jun-01 June Expenses:Books $60.00 $32.73
+08-Jun-30 End of June Expenses:Books $60.00 $35.00
+08-Jul-01 July Expenses:Books $70.00 $37.69
+08-Jul-31 End of July Expenses:Books $70.00 $40.00
+08-Aug-01 August Expenses:Books $80.00 $42.67
+08-Aug-31 End of August Expenses:Books $80.00 $45.00
+08-Sep-01 September Expenses:Books $90.00 $47.65
+08-Sep-30 End of September Expenses:Books $90.00 $50.00
+08-Oct-01 October Expenses:Books $100.00 $52.63
+08-Oct-31 End of October Expenses:Books $100.00 $55.00
+08-Nov-01 November Expenses:Books $110.00 $57.62
+08-Nov-30 End of November Expenses:Books $110.00 $60.00
+08-Dec-01 December Expenses:Books $120.00 $62.61
+08-Dec-31 End of December Expenses:Books $120.00 $65.00
+09-Jan-01 January Expenses:Books $10.00 $62.80
+09-Jan-31 End of January Expenses:Books $10.00 $60.77
+09-Feb-01 February Expenses:Books $20.00 $59.26
+09-Feb-28 End of February Expenses:Books $20.00 $57.86
+09-Mar-01 March Expenses:Books $30.00 $56.90
+09-Mar-31 End of March Expenses:Books $30.00 $56.00
+09-Apr-01 April Expenses:Books $40.00 $55.48
+09-Apr-30 End of April Expenses:Books $40.00 $55.00
+09-May-01 May Expenses:Books $50.00 $54.85
+09-May-31 End of May Expenses:Books $50.00 $54.71
+09-Jun-01 June Expenses:Books $60.00 $54.86
+09-Jun-30 End of June Expenses:Books $60.00 $55.00
+09-Jul-01 July Expenses:Books $70.00 $55.41
+09-Jul-31 End of July Expenses:Books $70.00 $55.79
+09-Aug-01 August Expenses:Books $80.00 $56.41
+09-Aug-31 End of August Expenses:Books $80.00 $57.00
+09-Sep-01 September Expenses:Books $90.00 $57.80
+09-Sep-30 End of September Expenses:Books $90.00 $58.57
+09-Oct-01 October Expenses:Books $100.00 $59.53
+09-Oct-31 End of October Expenses:Books $100.00 $60.45
+09-Nov-01 November Expenses:Books $110.00 $61.56
+09-Nov-30 End of November Expenses:Books $110.00 $62.61
+09-Dec-01 December Expenses:Books $120.00 $63.83
+09-Dec-31 End of December Expenses:Books $120.00 $65.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-balance-format.test b/test/baseline/opt-balance-format.test
new file mode 100644
index 00000000..5a39ded8
--- /dev/null
+++ b/test/baseline/opt-balance-format.test
@@ -0,0 +1,10 @@
+bal --balance-format='%(account)\n' --no-total
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+Assets:Investments:Vanguard:VMMXX
+Income:Dividends:Vanguard:VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-base.test b/test/baseline/opt-base.test
new file mode 100644
index 00000000..77912dbd
--- /dev/null
+++ b/test/baseline/opt-base.test
@@ -0,0 +1,29 @@
+bal --base
+<<<
+i 2007/03/01 23:00:00 A
+o 2007/03/02 01:00:00
+i 2007/03/11 23:00:00 B
+o 2007/03/12 01:00:00
+
+2006/05/22 * Company
+ Assets:Receivable $4,000.00
+ Income:Contracts -40h @ $100.00
+
+2006/05/22 * Company
+ Assets:Receivable $4,000.00
+ Income:Contracts -40h {$20} @ $100.00
+ Income:Gains $-3,200.00
+>>>1
+ 7200s A
+ $8,000.00 Assets:Receivable
+ 7200s B
+ $3,200.00 Equity:Capital Gains
+ $-3,200.00
+ -288000s Income
+ -288000s Contracts
+ $-3,200.00 Gains
+--------------------
+ $8,000.00
+ -273600s
+>>>2
+=== 0
diff --git a/test/baseline/opt-basis.test b/test/baseline/opt-basis.test
new file mode 100644
index 00000000..8270be88
--- /dev/null
+++ b/test/baseline/opt-basis.test
@@ -0,0 +1,12 @@
+bal --basis
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+ $0.35 Assets:Investments:Vanguard:VMMXX
+ $-0.35 Income:Dividends:Vanguard:VMMXX
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-begin.test b/test/baseline/opt-begin.test
new file mode 100644
index 00000000..17f4012e
--- /dev/null
+++ b/test/baseline/opt-begin.test
@@ -0,0 +1,240 @@
+reg --begin=2009/02
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+09-Feb-01 February Expenses:Books $20.00 $20.00
+ Assets:Cash $-20.00 0
+09-Feb-28 End of February Expenses:Books $20.00 $20.00
+ Assets:Cash $-20.00 0
+09-Mar-01 March Expenses:Books $30.00 $30.00
+ Assets:Cash $-30.00 0
+09-Mar-31 End of March Expenses:Books $30.00 $30.00
+ Assets:Cash $-30.00 0
+09-Apr-01 April Expenses:Books $40.00 $40.00
+ Assets:Cash $-40.00 0
+09-Apr-30 End of April Expenses:Books $40.00 $40.00
+ Assets:Cash $-40.00 0
+09-May-01 May Expenses:Books $50.00 $50.00
+ Assets:Cash $-50.00 0
+09-May-31 End of May Expenses:Books $50.00 $50.00
+ Assets:Cash $-50.00 0
+09-Jun-01 June Expenses:Books $60.00 $60.00
+ Assets:Cash $-60.00 0
+09-Jun-30 End of June Expenses:Books $60.00 $60.00
+ Assets:Cash $-60.00 0
+09-Jul-01 July Expenses:Books $70.00 $70.00
+ Assets:Cash $-70.00 0
+09-Jul-31 End of July Expenses:Books $70.00 $70.00
+ Assets:Cash $-70.00 0
+09-Aug-01 August Expenses:Books $80.00 $80.00
+ Assets:Cash $-80.00 0
+09-Aug-31 End of August Expenses:Books $80.00 $80.00
+ Assets:Cash $-80.00 0
+09-Sep-01 September Expenses:Books $90.00 $90.00
+ Assets:Cash $-90.00 0
+09-Sep-30 End of September Expenses:Books $90.00 $90.00
+ Assets:Cash $-90.00 0
+09-Oct-01 October Expenses:Books $100.00 $100.00
+ Assets:Cash $-100.00 0
+09-Oct-31 End of October Expenses:Books $100.00 $100.00
+ Assets:Cash $-100.00 0
+09-Nov-01 November Expenses:Books $110.00 $110.00
+ Assets:Cash $-110.00 0
+09-Nov-30 End of November Expenses:Books $110.00 $110.00
+ Assets:Cash $-110.00 0
+09-Dec-01 December Expenses:Books $120.00 $120.00
+ Assets:Cash $-120.00 0
+09-Dec-31 End of December Expenses:Books $120.00 $120.00
+ Assets:Cash $-120.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-budget.test b/test/baseline/opt-budget.test
new file mode 100644
index 00000000..eb2ade9d
--- /dev/null
+++ b/test/baseline/opt-budget.test
@@ -0,0 +1,321 @@
+reg --budget books
+<<<
+~ monthly
+ Expenses:Books $10.00
+ Liabilities $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 Budget transaction Expenses:Books $-10.00 $-10.00
+08-Jan-01 January Expenses:Books $10.00 0
+08-Jan-31 End of January Expenses:Books $10.00 $10.00
+08-Feb-01 Budget transaction Expenses:Books $-10.00 0
+08-Feb-01 February Expenses:Books $20.00 $20.00
+08-Feb-28 End of February Expenses:Books $20.00 $40.00
+08-Mar-01 Budget transaction Expenses:Books $-10.00 $30.00
+08-Mar-01 March Expenses:Books $30.00 $60.00
+08-Mar-31 End of March Expenses:Books $30.00 $90.00
+08-Apr-01 Budget transaction Expenses:Books $-10.00 $80.00
+08-Apr-01 April Expenses:Books $40.00 $120.00
+08-Apr-30 End of April Expenses:Books $40.00 $160.00
+08-May-01 Budget transaction Expenses:Books $-10.00 $150.00
+08-May-01 May Expenses:Books $50.00 $200.00
+08-May-31 End of May Expenses:Books $50.00 $250.00
+08-Jun-01 Budget transaction Expenses:Books $-10.00 $240.00
+08-Jun-01 June Expenses:Books $60.00 $300.00
+08-Jun-30 End of June Expenses:Books $60.00 $360.00
+08-Jul-01 Budget transaction Expenses:Books $-10.00 $350.00
+08-Jul-01 July Expenses:Books $70.00 $420.00
+08-Jul-31 End of July Expenses:Books $70.00 $490.00
+08-Aug-01 Budget transaction Expenses:Books $-10.00 $480.00
+08-Aug-01 August Expenses:Books $80.00 $560.00
+08-Aug-31 End of August Expenses:Books $80.00 $640.00
+08-Sep-01 Budget transaction Expenses:Books $-10.00 $630.00
+08-Sep-01 September Expenses:Books $90.00 $720.00
+08-Sep-30 End of September Expenses:Books $90.00 $810.00
+08-Oct-01 Budget transaction Expenses:Books $-10.00 $800.00
+08-Oct-01 October Expenses:Books $100.00 $900.00
+08-Oct-31 End of October Expenses:Books $100.00 $1000.00
+08-Nov-01 Budget transaction Expenses:Books $-10.00 $990.00
+08-Nov-01 November Expenses:Books $110.00 $1100.00
+08-Nov-30 End of November Expenses:Books $110.00 $1210.00
+08-Dec-01 Budget transaction Expenses:Books $-10.00 $1200.00
+08-Dec-01 December Expenses:Books $120.00 $1320.00
+08-Dec-31 End of December Expenses:Books $120.00 $1440.00
+09-Jan-01 Budget transaction Expenses:Books $-10.00 $1430.00
+09-Jan-01 January Expenses:Books $10.00 $1440.00
+09-Jan-31 End of January Expenses:Books $10.00 $1450.00
+09-Feb-01 Budget transaction Expenses:Books $-10.00 $1440.00
+09-Feb-01 February Expenses:Books $20.00 $1460.00
+09-Feb-28 End of February Expenses:Books $20.00 $1480.00
+09-Mar-01 Budget transaction Expenses:Books $-10.00 $1470.00
+09-Mar-01 March Expenses:Books $30.00 $1500.00
+09-Mar-31 End of March Expenses:Books $30.00 $1530.00
+09-Apr-01 Budget transaction Expenses:Books $-10.00 $1520.00
+09-Apr-01 April Expenses:Books $40.00 $1560.00
+09-Apr-30 End of April Expenses:Books $40.00 $1600.00
+09-May-01 Budget transaction Expenses:Books $-10.00 $1590.00
+09-May-01 May Expenses:Books $50.00 $1640.00
+09-May-31 End of May Expenses:Books $50.00 $1690.00
+09-Jun-01 Budget transaction Expenses:Books $-10.00 $1680.00
+09-Jun-01 June Expenses:Books $60.00 $1740.00
+09-Jun-30 End of June Expenses:Books $60.00 $1800.00
+09-Jul-01 Budget transaction Expenses:Books $-10.00 $1790.00
+09-Jul-01 July Expenses:Books $70.00 $1860.00
+09-Jul-31 End of July Expenses:Books $70.00 $1930.00
+09-Aug-01 Budget transaction Expenses:Books $-10.00 $1920.00
+09-Aug-01 August Expenses:Books $80.00 $2000.00
+09-Aug-31 End of August Expenses:Books $80.00 $2080.00
+09-Sep-01 Budget transaction Expenses:Books $-10.00 $2070.00
+09-Sep-01 September Expenses:Books $90.00 $2160.00
+09-Sep-30 End of September Expenses:Books $90.00 $2250.00
+09-Oct-01 Budget transaction Expenses:Books $-10.00 $2240.00
+09-Oct-01 October Expenses:Books $100.00 $2340.00
+09-Oct-31 End of October Expenses:Books $100.00 $2440.00
+09-Nov-01 Budget transaction Expenses:Books $-10.00 $2430.00
+09-Nov-01 November Expenses:Books $110.00 $2540.00
+09-Nov-30 End of November Expenses:Books $110.00 $2650.00
+09-Dec-01 Budget transaction Expenses:Books $-10.00 $2640.00
+09-Dec-01 December Expenses:Books $120.00 $2760.00
+09-Dec-31 End of December Expenses:Books $120.00 $2880.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-by-payee.test b/test/baseline/opt-by-payee.test
new file mode 100644
index 00000000..ec8d0a73
--- /dev/null
+++ b/test/baseline/opt-by-payee.test
@@ -0,0 +1,220 @@
+reg --by-payee not @End
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Assets:Cash $-20.00 $-20.00
+ Expenses:Books $20.00 0
+08-Feb-01 February Assets:Cash $-40.00 $-40.00
+ Expenses:Books $40.00 0
+08-Mar-01 March Assets:Cash $-60.00 $-60.00
+ Expenses:Books $60.00 0
+08-Apr-01 April Assets:Cash $-80.00 $-80.00
+ Expenses:Books $80.00 0
+08-May-01 May Assets:Cash $-100.00 $-100.00
+ Expenses:Books $100.00 0
+08-Jun-01 June Assets:Cash $-120.00 $-120.00
+ Expenses:Books $120.00 0
+08-Jul-01 July Assets:Cash $-140.00 $-140.00
+ Expenses:Books $140.00 0
+08-Aug-01 August Assets:Cash $-160.00 $-160.00
+ Expenses:Books $160.00 0
+08-Sep-01 September Assets:Cash $-180.00 $-180.00
+ Expenses:Books $180.00 0
+08-Oct-01 October Assets:Cash $-200.00 $-200.00
+ Expenses:Books $200.00 0
+08-Nov-01 November Assets:Cash $-220.00 $-220.00
+ Expenses:Books $220.00 0
+08-Dec-01 December Assets:Cash $-240.00 $-240.00
+ Expenses:Books $240.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-cleared.test b/test/baseline/opt-cleared.test
new file mode 100644
index 00000000..8c08834c
--- /dev/null
+++ b/test/baseline/opt-cleared.test
@@ -0,0 +1,206 @@
+reg --cleared
+<<<
+2008/01/01 * January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 * February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 * March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ * Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ * Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ * Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ * Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Expenses:Books $10.00 $10.00
+ Assets:Cash $-10.00 0
+08-Feb-01 February Expenses:Books $20.00 $20.00
+ Assets:Cash $-20.00 0
+08-Mar-01 March Expenses:Books $30.00 $30.00
+ Assets:Cash $-30.00 0
+08-Apr-01 April Expenses:Books $40.00 $40.00
+08-Apr-30 End of April Expenses:Books $40.00 $80.00
+08-May-01 May Assets:Cash $-50.00 $30.00
+08-May-31 End of May Assets:Cash $-50.00 $-20.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-code-as-account.test b/test/baseline/opt-code-as-account.test
new file mode 100644
index 00000000..c669427e
--- /dev/null
+++ b/test/baseline/opt-code-as-account.test
@@ -0,0 +1,34 @@
+reg --account=code
+<<<
+2008/01/01 * (100) January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 (101) End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 * (102) February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 (103) End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 * March
+ Expenses:Books $30.00
+ Assets:Cash
+>>>1
+08-Jan-01 January 100 $10.00 $10.00
+08-Jan-01 January 100 $-10.00 0
+08-Jan-31 End of January 101 $10.00 $10.00
+08-Jan-31 End of January 101 $-10.00 0
+08-Feb-01 February 102 $20.00 $20.00
+08-Feb-01 February 102 $-20.00 0
+08-Feb-28 End of February 103 $20.00 $20.00
+08-Feb-28 End of February 103 $-20.00 0
+08-Mar-01 March $30.00 $30.00
+08-Mar-01 March $-30.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-code-as-payee.test b/test/baseline/opt-code-as-payee.test
new file mode 100644
index 00000000..c2988626
--- /dev/null
+++ b/test/baseline/opt-code-as-payee.test
@@ -0,0 +1,34 @@
+reg --payee=code
+<<<
+2008/01/01 * (100) January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 (101) End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 * (102) February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 (103) End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 * March
+ Expenses:Books $30.00
+ Assets:Cash
+>>>1
+08-Jan-01 100 Expenses:Books $10.00 $10.00
+08-Jan-01 100 Assets:Cash $-10.00 0
+08-Jan-31 101 Expenses:Books $10.00 $10.00
+08-Jan-31 101 Assets:Cash $-10.00 0
+08-Feb-01 102 Expenses:Books $20.00 $20.00
+08-Feb-01 102 Assets:Cash $-20.00 0
+08-Feb-28 103 Expenses:Books $20.00 $20.00
+08-Feb-28 103 Assets:Cash $-20.00 0
+08-Mar-01 Expenses:Books $30.00 $30.00
+08-Mar-01 Assets:Cash $-30.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-collapse-if-zero.test b/test/baseline/opt-collapse-if-zero.test
new file mode 100644
index 00000000..fb4d33fd
--- /dev/null
+++ b/test/baseline/opt-collapse-if-zero.test
@@ -0,0 +1,15 @@
+reg --collapse-if-zero
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX $0.35
+ Income:Dividends:Vanguard:VMMXX $-0.35
+
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-collapse.test b/test/baseline/opt-collapse.test
new file mode 100644
index 00000000..afe59840
--- /dev/null
+++ b/test/baseline/opt-collapse.test
@@ -0,0 +1,13 @@
+bal --collapse
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+ 0.350 VMMXX Assets
+ $-0.35 Income
+--------------------
+ $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-collapse_reg.test b/test/baseline/opt-collapse_reg.test
new file mode 100644
index 00000000..12d4a2d9
--- /dev/null
+++ b/test/baseline/opt-collapse_reg.test
@@ -0,0 +1,46 @@
+reg --collapse food
+<<<
+2009/10/01 Test
+ Expenses:Food:Dining $10
+ Expenses:Food:Tips $1
+ Assets:Cash
+
+2009/10/02 Test
+ Expenses:Food:Dining $10
+ Expenses:Food:Tips $1
+ Assets:Cash
+
+2009/10/03 Test
+ Expenses:Food:Dining $10
+ Expenses:Food:Tips $1
+ Assets:Cash
+
+2009/10/04 Test
+ Expenses:Food:Dining $10
+ Expenses:Food:Tips $1
+ Assets:Cash
+
+2009/10/05 Test
+ Expenses:Food:Dining $10
+ Expenses:Food:Tips $1
+ Assets:Cash
+
+2009/10/06 Test
+ Expenses:Food:Dining $10
+ Expenses:Food:Tips $1
+ Assets:Cash
+
+2009/10/07 Test
+ Expenses:Food:Dining $10
+ Expenses:Food:Tips $1
+ Assets:Cash
+>>>1
+09-Oct-01 Test <Total> $11 $11
+09-Oct-02 Test <Total> $11 $22
+09-Oct-03 Test <Total> $11 $33
+09-Oct-04 Test <Total> $11 $44
+09-Oct-05 Test <Total> $11 $55
+09-Oct-06 Test <Total> $11 $66
+09-Oct-07 Test <Total> $11 $77
+>>>2
+=== 0
diff --git a/test/baseline/opt-color.test b/test/baseline/opt-color.test
new file mode 100644
index 00000000..6520c7dc
--- /dev/null
+++ b/test/baseline/opt-color.test
@@ -0,0 +1,13 @@
+bal --color --force-color
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+ 0.350 VMMXX Assets:Investments:Vanguard:VMMXX
+ $-0.35 Income:Dividends:Vanguard:VMMXX
+--------------------
+ $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-columns.test b/test/baseline/opt-columns.test
new file mode 100644
index 00000000..4dc28d9b
--- /dev/null
+++ b/test/baseline/opt-columns.test
@@ -0,0 +1,11 @@
+reg --columns=100
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:Investments:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ In:Dividends:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-commodity-as-account.test b/test/baseline/opt-commodity-as-account.test
new file mode 100644
index 00000000..44fb0028
--- /dev/null
+++ b/test/baseline/opt-commodity-as-account.test
@@ -0,0 +1,11 @@
+reg --account=commodity
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX VMMXX 0.350 VMMXX 0.350 VMMXX
+07-Feb-02 RD VMMXX $ $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-commodity-as-payee.test b/test/baseline/opt-commodity-as-payee.test
new file mode 100644
index 00000000..2f829b4a
--- /dev/null
+++ b/test/baseline/opt-commodity-as-payee.test
@@ -0,0 +1,11 @@
+reg --payee=commodity
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+07-Feb-02 $ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-cost.test b/test/baseline/opt-cost.test
new file mode 100644
index 00000000..b84646d8
--- /dev/null
+++ b/test/baseline/opt-cost.test
@@ -0,0 +1,12 @@
+bal --cost
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+ $0.35 Assets:Investments:Vanguard:VMMXX
+ $-0.35 Income:Dividends:Vanguard:VMMXX
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-csv-format.test b/test/baseline/opt-csv-format.test
new file mode 100644
index 00000000..d4975f93
--- /dev/null
+++ b/test/baseline/opt-csv-format.test
@@ -0,0 +1,10 @@
+csv --csv-format='"%(date)"\n'
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+"2007/02/02"
+"2007/02/02"
+>>>2
+=== 0
diff --git a/test/baseline/opt-current.test b/test/baseline/opt-current.test
new file mode 100644
index 00000000..1367fad1
--- /dev/null
+++ b/test/baseline/opt-current.test
@@ -0,0 +1,17 @@
+bal --current
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+
+2700/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+ 0.350 VMMXX Assets:Investments:Vanguard:VMMXX
+ $-0.35 Income:Dividends:Vanguard:VMMXX
+--------------------
+ $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-daily.test b/test/baseline/opt-daily.test
new file mode 100644
index 00000000..0ff3987f
--- /dev/null
+++ b/test/baseline/opt-daily.test
@@ -0,0 +1,56 @@
+reg --daily
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+>>>1
+08-Jan-01 - 08-Jan-01 Assets:Cash $-60.00 $-60.00
+ Expenses:Books $60.00 0
+08-Feb-01 - 08-Feb-01 Assets:Cash $-120.00 $-120.00
+ Expenses:Books $120.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-date-format.test b/test/baseline/opt-date-format.test
new file mode 100644
index 00000000..b4e1a332
--- /dev/null
+++ b/test/baseline/opt-date-format.test
@@ -0,0 +1,11 @@
+reg --date-format='%Y'
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+2007 RD VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-date-width.test b/test/baseline/opt-date-width.test
new file mode 100644
index 00000000..47652099
--- /dev/null
+++ b/test/baseline/opt-date-width.test
@@ -0,0 +1,11 @@
+reg --date-width=20
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-depth.test b/test/baseline/opt-depth.test
new file mode 100644
index 00000000..4b378fac
--- /dev/null
+++ b/test/baseline/opt-depth.test
@@ -0,0 +1,93 @@
+bal --depth 1
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:One:Books $10.00
+ Expenses:One:Two:Books $10.00
+ Expenses:One:Two:Three:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Assets:Cash 0
+ Income:Books
+
+2008/01/01 January
+ Assets:Cash
+ Income:One:Books $-10.00
+ Income:One:Two:Books $-10.00
+ Income:One:Two:Three:Books $-10.00
+>>>1
+ $-10.00 Assets
+ $40.00 Expenses
+ $-30.00 Income
+--------------------
+ 0
+>>>2
+=== 0
+bal --depth 2
+>>>1
+ $-10.00 Assets:Cash
+ $40.00 Expenses
+ $10.00 Books
+ $30.00 One
+ $-30.00 Income:One
+--------------------
+ 0
+>>>2
+=== 0
+bal --depth 3
+>>>1
+ $-10.00 Assets:Cash
+ $40.00 Expenses
+ $10.00 Books
+ $30.00 One
+ $10.00 Books
+ $20.00 Two
+ $-30.00 Income:One
+ $-10.00 Books
+ $-20.00 Two
+--------------------
+ 0
+>>>2
+=== 0
+bal --depth 4
+>>>1
+ $-10.00 Assets:Cash
+ $40.00 Expenses
+ $10.00 Books
+ $30.00 One
+ $10.00 Books
+ $20.00 Two
+ $10.00 Books
+ $10.00 Three
+ $-30.00 Income:One
+ $-10.00 Books
+ $-20.00 Two
+ $-10.00 Books
+ $-10.00 Three
+--------------------
+ 0
+>>>2
+=== 0
+bal --depth 5
+>>>1
+ $-10.00 Assets:Cash
+ $40.00 Expenses
+ $10.00 Books
+ $30.00 One
+ $10.00 Books
+ $20.00 Two
+ $10.00 Books
+ $10.00 Three:Books
+ $-30.00 Income:One
+ $-10.00 Books
+ $-20.00 Two
+ $-10.00 Books
+ $-10.00 Three:Books
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-depth_flat.test b/test/baseline/opt-depth_flat.test
new file mode 100644
index 00000000..85f29423
--- /dev/null
+++ b/test/baseline/opt-depth_flat.test
@@ -0,0 +1,68 @@
+bal --depth 1 --flat
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:One:Books $10.00
+ Expenses:One:Two:Books $10.00
+ Expenses:One:Two:Three:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Assets:Cash 0
+ Income:Books
+
+2008/01/01 January
+ Assets:Cash
+ Income:One:Books $-10.00
+ Income:One:Two:Books $-10.00
+ Income:One:Two:Three:Books $-10.00
+>>>1
+>>>2
+=== 0
+bal --depth 2 --flat
+>>>1
+ $-10.00 Assets:Cash
+ $10.00 Expenses:Books
+--------------------
+ 0
+>>>2
+=== 0
+bal --depth 3 --flat
+>>>1
+ $-10.00 Assets:Cash
+ $10.00 Expenses:Books
+ $10.00 Expenses:One:Books
+ $-10.00 Income:One:Books
+--------------------
+ 0
+>>>2
+=== 0
+bal --depth 4 --flat
+>>>1
+ $-10.00 Assets:Cash
+ $10.00 Expenses:Books
+ $10.00 Expenses:One:Books
+ $10.00 Expenses:One:Two:Books
+ $-10.00 Income:One:Books
+ $-10.00 Income:One:Two:Books
+--------------------
+ 0
+>>>2
+=== 0
+bal --depth 5 --flat
+>>>1
+ $-10.00 Assets:Cash
+ $10.00 Expenses:Books
+ $10.00 Expenses:One:Books
+ $10.00 Expenses:One:Two:Books
+ $10.00 Expenses:One:Two:Three:Books
+ $-10.00 Income:One:Books
+ $-10.00 Income:One:Two:Books
+ $-10.00 Income:One:Two:Three:Books
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-deviation.test b/test/baseline/opt-deviation.test
new file mode 100644
index 00000000..50e625de
--- /dev/null
+++ b/test/baseline/opt-deviation.test
@@ -0,0 +1,244 @@
+reg --deviation books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Expenses:Books $10.00 0
+08-Jan-31 End of January Expenses:Books $10.00 0
+08-Feb-01 February Expenses:Books $20.00 $6.67
+08-Feb-28 End of February Expenses:Books $20.00 $5.00
+08-Mar-01 March Expenses:Books $30.00 $12.00
+08-Mar-31 End of March Expenses:Books $30.00 $10.00
+08-Apr-01 April Expenses:Books $40.00 $17.14
+08-Apr-30 End of April Expenses:Books $40.00 $15.00
+08-May-01 May Expenses:Books $50.00 $22.22
+08-May-31 End of May Expenses:Books $50.00 $20.00
+08-Jun-01 June Expenses:Books $60.00 $27.27
+08-Jun-30 End of June Expenses:Books $60.00 $25.00
+08-Jul-01 July Expenses:Books $70.00 $32.31
+08-Jul-31 End of July Expenses:Books $70.00 $30.00
+08-Aug-01 August Expenses:Books $80.00 $37.33
+08-Aug-31 End of August Expenses:Books $80.00 $35.00
+08-Sep-01 September Expenses:Books $90.00 $42.35
+08-Sep-30 End of September Expenses:Books $90.00 $40.00
+08-Oct-01 October Expenses:Books $100.00 $47.37
+08-Oct-31 End of October Expenses:Books $100.00 $45.00
+08-Nov-01 November Expenses:Books $110.00 $52.38
+08-Nov-30 End of November Expenses:Books $110.00 $50.00
+08-Dec-01 December Expenses:Books $120.00 $57.39
+08-Dec-31 End of December Expenses:Books $120.00 $55.00
+09-Jan-01 January Expenses:Books $10.00 $-52.80
+09-Jan-31 End of January Expenses:Books $10.00 $-50.77
+09-Feb-01 February Expenses:Books $20.00 $-39.26
+09-Feb-28 End of February Expenses:Books $20.00 $-37.86
+09-Mar-01 March Expenses:Books $30.00 $-26.90
+09-Mar-31 End of March Expenses:Books $30.00 $-26.00
+09-Apr-01 April Expenses:Books $40.00 $-15.48
+09-Apr-30 End of April Expenses:Books $40.00 $-15.00
+09-May-01 May Expenses:Books $50.00 $-4.85
+09-May-31 End of May Expenses:Books $50.00 $-4.71
+09-Jun-01 June Expenses:Books $60.00 $5.14
+09-Jun-30 End of June Expenses:Books $60.00 $5.00
+09-Jul-01 July Expenses:Books $70.00 $14.59
+09-Jul-31 End of July Expenses:Books $70.00 $14.21
+09-Aug-01 August Expenses:Books $80.00 $23.59
+09-Aug-31 End of August Expenses:Books $80.00 $23.00
+09-Sep-01 September Expenses:Books $90.00 $32.20
+09-Sep-30 End of September Expenses:Books $90.00 $31.43
+09-Oct-01 October Expenses:Books $100.00 $40.47
+09-Oct-31 End of October Expenses:Books $100.00 $39.55
+09-Nov-01 November Expenses:Books $110.00 $48.44
+09-Nov-30 End of November Expenses:Books $110.00 $47.39
+09-Dec-01 December Expenses:Books $120.00 $56.17
+09-Dec-31 End of December Expenses:Books $120.00 $55.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-display-amount.test b/test/baseline/opt-display-amount.test
new file mode 100644
index 00000000..45eac079
--- /dev/null
+++ b/test/baseline/opt-display-amount.test
@@ -0,0 +1,65 @@
+reg --display-amount='amount * 10' books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+>>>1
+08-Jan-01 January Expenses:Books $100.00 $10.00
+08-Jan-01 End of January Expenses:Books $100.00 $20.00
+08-Jan-01 January Expenses:Books $100.00 $30.00
+08-Jan-01 End of January Expenses:Books $100.00 $40.00
+08-Jan-01 January Expenses:Books $100.00 $50.00
+08-Jan-01 End of January Expenses:Books $100.00 $60.00
+08-Feb-01 February Expenses:Books $200.00 $80.00
+08-Feb-01 End of February Expenses:Books $200.00 $100.00
+08-Feb-01 February Expenses:Books $200.00 $120.00
+08-Feb-01 End of February Expenses:Books $200.00 $140.00
+08-Feb-01 February Expenses:Books $200.00 $160.00
+08-Feb-01 End of February Expenses:Books $200.00 $180.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-display-total.test b/test/baseline/opt-display-total.test
new file mode 100644
index 00000000..9a6e67d6
--- /dev/null
+++ b/test/baseline/opt-display-total.test
@@ -0,0 +1,65 @@
+reg --display-total='amount * 10' books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+>>>1
+08-Jan-01 January Expenses:Books $10.00 $100.00
+08-Jan-01 End of January Expenses:Books $10.00 $100.00
+08-Jan-01 January Expenses:Books $10.00 $100.00
+08-Jan-01 End of January Expenses:Books $10.00 $100.00
+08-Jan-01 January Expenses:Books $10.00 $100.00
+08-Jan-01 End of January Expenses:Books $10.00 $100.00
+08-Feb-01 February Expenses:Books $20.00 $200.00
+08-Feb-01 End of February Expenses:Books $20.00 $200.00
+08-Feb-01 February Expenses:Books $20.00 $200.00
+08-Feb-01 End of February Expenses:Books $20.00 $200.00
+08-Feb-01 February Expenses:Books $20.00 $200.00
+08-Feb-01 End of February Expenses:Books $20.00 $200.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-display.test b/test/baseline/opt-display.test
new file mode 100644
index 00000000..4f01a706
--- /dev/null
+++ b/test/baseline/opt-display.test
@@ -0,0 +1,59 @@
+reg --display='payee =~ /February/' books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+>>>1
+08-Feb-01 February Expenses:Books $20.00 $80.00
+08-Feb-01 End of February Expenses:Books $20.00 $100.00
+08-Feb-01 February Expenses:Books $20.00 $120.00
+08-Feb-01 End of February Expenses:Books $20.00 $140.00
+08-Feb-01 February Expenses:Books $20.00 $160.00
+08-Feb-01 End of February Expenses:Books $20.00 $180.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-dow.test b/test/baseline/opt-dow.test
new file mode 100644
index 00000000..bbd5aa0c
--- /dev/null
+++ b/test/baseline/opt-dow.test
@@ -0,0 +1,55 @@
+reg --dow books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/01 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+>>>1
+08-Jan-01 Tuesdays Expenses:Books $60.00 $60.00
+08-Feb-01 Fridays Expenses:Books $120.00 $180.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-effective.test b/test/baseline/opt-effective.test
new file mode 100644
index 00000000..adf9f8af
--- /dev/null
+++ b/test/baseline/opt-effective.test
@@ -0,0 +1,22 @@
+reg --effective
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31=2008/01/01 End of January
+ Expenses:Books $10.00 ; [=2008/02/01]
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Expenses:Books $10.00 $10.00
+ Assets:Cash $-10.00 0
+08-Jan-01 End of January Assets:Cash $-10.00 $-10.00
+08-Feb-01 End of January Expenses:Books $10.00 0
+08-Feb-01 February Expenses:Books $20.00 $20.00
+ Assets:Cash $-20.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-empty.test b/test/baseline/opt-empty.test
new file mode 100644
index 00000000..507767ed
--- /dev/null
+++ b/test/baseline/opt-empty.test
@@ -0,0 +1,36 @@
+reg --empty
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:One:Books $10.00
+ Expenses:One:Two:Books $10.00
+ Expenses:One:Two:Three:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Assets:Cash 0
+ Income:Books
+
+2008/01/01 January
+ Assets:Cash
+ Income:One:Books $-10.00
+ Income:One:Two:Books $-10.00
+ Income:One:Two:Three:Books $-10.00
+>>>1
+08-Jan-01 January Expenses:Books $10.00 $10.00
+ Assets:Cash $-10.00 0
+08-Jan-01 January Expenses:One:Books $10.00 $10.00
+ Expenses:One:Two:Books $10.00 $20.00
+ Ex:One:Two:Three:Books $10.00 $30.00
+ Assets:Cash $-30.00 0
+08-Jan-01 January Assets:Cash 0 0
+ Income:Books 0 0
+08-Jan-01 January Assets:Cash $30.00 $30.00
+ Income:One:Books $-10.00 $20.00
+ Income:One:Two:Books $-10.00 $10.00
+ In:One:Two:Three:Books $-10.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-empty_bal.test b/test/baseline/opt-empty_bal.test
new file mode 100644
index 00000000..f8e7560b
--- /dev/null
+++ b/test/baseline/opt-empty_bal.test
@@ -0,0 +1,41 @@
+bal --empty
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:One:Books $10.00
+ Expenses:One:Two:Books $10.00
+ Expenses:One:Two:Three:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Assets:Cash 0
+ Income:Books
+
+2008/01/01 January
+ Assets:Cash
+ Income:One:Books $-10.00
+ Income:One:Two:Books $-10.00
+ Income:One:Two:Three:Books $-10.00
+>>>1
+ $-10.00 Assets:Cash
+ $40.00 Expenses
+ $10.00 Books
+ $30.00 One
+ $10.00 Books
+ $20.00 Two
+ $10.00 Books
+ $10.00 Three:Books
+ $-30.00 Income
+ 0 Books
+ $-30.00 One
+ $-10.00 Books
+ $-20.00 Two
+ $-10.00 Books
+ $-10.00 Three:Books
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-empty_bal_flat.test b/test/baseline/opt-empty_bal_flat.test
new file mode 100644
index 00000000..338c0bf8
--- /dev/null
+++ b/test/baseline/opt-empty_bal_flat.test
@@ -0,0 +1,35 @@
+bal --empty --flat
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:One:Books $10.00
+ Expenses:One:Two:Books $10.00
+ Expenses:One:Two:Three:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Assets:Cash 0
+ Income:Books
+
+2008/01/01 January
+ Assets:Cash
+ Income:One:Books $-10.00
+ Income:One:Two:Books $-10.00
+ Income:One:Two:Three:Books $-10.00
+>>>1
+ $-10.00 Assets:Cash
+ $10.00 Expenses:Books
+ $10.00 Expenses:One:Books
+ $10.00 Expenses:One:Two:Books
+ $10.00 Expenses:One:Two:Three:Books
+ 0 Income:Books
+ $-10.00 Income:One:Books
+ $-10.00 Income:One:Two:Books
+ $-10.00 Income:One:Two:Three:Books
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-empty_collapse.test b/test/baseline/opt-empty_collapse.test
new file mode 100644
index 00000000..3e22a9b1
--- /dev/null
+++ b/test/baseline/opt-empty_collapse.test
@@ -0,0 +1,28 @@
+reg --empty --collapse
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:One:Books $10.00
+ Expenses:One:Two:Books $10.00
+ Expenses:One:Two:Three:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Assets:Cash 0
+ Income:Books
+
+2008/01/01 January
+ Assets:Cash
+ Income:One:Books $-10.00
+ Income:One:Two:Books $-10.00
+ Income:One:Two:Three:Books $-10.00
+>>>1
+08-Jan-01 January <Total> 0 0
+08-Jan-01 January <Total> 0 0
+08-Jan-01 January <Total> 0 0
+08-Jan-01 January <Total> 0 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-end.test b/test/baseline/opt-end.test
new file mode 100644
index 00000000..d5c7f5c0
--- /dev/null
+++ b/test/baseline/opt-end.test
@@ -0,0 +1,248 @@
+reg --end=2009/02
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Expenses:Books $10.00 $10.00
+ Assets:Cash $-10.00 0
+08-Jan-31 End of January Expenses:Books $10.00 $10.00
+ Assets:Cash $-10.00 0
+08-Feb-01 February Expenses:Books $20.00 $20.00
+ Assets:Cash $-20.00 0
+08-Feb-28 End of February Expenses:Books $20.00 $20.00
+ Assets:Cash $-20.00 0
+08-Mar-01 March Expenses:Books $30.00 $30.00
+ Assets:Cash $-30.00 0
+08-Mar-31 End of March Expenses:Books $30.00 $30.00
+ Assets:Cash $-30.00 0
+08-Apr-01 April Expenses:Books $40.00 $40.00
+ Assets:Cash $-40.00 0
+08-Apr-30 End of April Expenses:Books $40.00 $40.00
+ Assets:Cash $-40.00 0
+08-May-01 May Expenses:Books $50.00 $50.00
+ Assets:Cash $-50.00 0
+08-May-31 End of May Expenses:Books $50.00 $50.00
+ Assets:Cash $-50.00 0
+08-Jun-01 June Expenses:Books $60.00 $60.00
+ Assets:Cash $-60.00 0
+08-Jun-30 End of June Expenses:Books $60.00 $60.00
+ Assets:Cash $-60.00 0
+08-Jul-01 July Expenses:Books $70.00 $70.00
+ Assets:Cash $-70.00 0
+08-Jul-31 End of July Expenses:Books $70.00 $70.00
+ Assets:Cash $-70.00 0
+08-Aug-01 August Expenses:Books $80.00 $80.00
+ Assets:Cash $-80.00 0
+08-Aug-31 End of August Expenses:Books $80.00 $80.00
+ Assets:Cash $-80.00 0
+08-Sep-01 September Expenses:Books $90.00 $90.00
+ Assets:Cash $-90.00 0
+08-Sep-30 End of September Expenses:Books $90.00 $90.00
+ Assets:Cash $-90.00 0
+08-Oct-01 October Expenses:Books $100.00 $100.00
+ Assets:Cash $-100.00 0
+08-Oct-31 End of October Expenses:Books $100.00 $100.00
+ Assets:Cash $-100.00 0
+08-Nov-01 November Expenses:Books $110.00 $110.00
+ Assets:Cash $-110.00 0
+08-Nov-30 End of November Expenses:Books $110.00 $110.00
+ Assets:Cash $-110.00 0
+08-Dec-01 December Expenses:Books $120.00 $120.00
+ Assets:Cash $-120.00 0
+08-Dec-31 End of December Expenses:Books $120.00 $120.00
+ Assets:Cash $-120.00 0
+09-Jan-01 January Expenses:Books $10.00 $10.00
+ Assets:Cash $-10.00 0
+09-Jan-31 End of January Expenses:Books $10.00 $10.00
+ Assets:Cash $-10.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-equity.test b/test/baseline/opt-equity.test
new file mode 100644
index 00000000..b09e9ad0
--- /dev/null
+++ b/test/baseline/opt-equity.test
@@ -0,0 +1,11 @@
+equity assets
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+2007/02/02 Opening Balances
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX
+ Equity:Opening Balances -0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-exact.test b/test/baseline/opt-exact.test
new file mode 100644
index 00000000..358f1dc4
--- /dev/null
+++ b/test/baseline/opt-exact.test
@@ -0,0 +1,225 @@
+reg --weekly --exact books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 - 08-Jan-01 Expenses:Books $10.00 $10.00
+08-Jan-31 - 08-Feb-01 Expenses:Books $30.00 $40.00
+08-Feb-28 - 08-Mar-01 Expenses:Books $50.00 $90.00
+08-Mar-31 - 08-Apr-01 Expenses:Books $70.00 $160.00
+08-Apr-30 - 08-May-01 Expenses:Books $90.00 $250.00
+08-May-31 - 08-May-31 Expenses:Books $50.00 $300.00
+08-Jun-01 - 08-Jun-01 Expenses:Books $60.00 $360.00
+08-Jun-30 - 08-Jul-01 Expenses:Books $130.00 $490.00
+08-Jul-31 - 08-Aug-01 Expenses:Books $150.00 $640.00
+08-Aug-31 - 08-Sep-01 Expenses:Books $170.00 $810.00
+08-Sep-30 - 08-Oct-01 Expenses:Books $190.00 $1000.00
+08-Oct-31 - 08-Nov-01 Expenses:Books $210.00 $1210.00
+08-Nov-30 - 08-Dec-01 Expenses:Books $230.00 $1440.00
+08-Dec-31 - 09-Jan-01 Expenses:Books $130.00 $1570.00
+09-Jan-31 - 09-Jan-31 Expenses:Books $10.00 $1580.00
+09-Feb-01 - 09-Feb-01 Expenses:Books $20.00 $1600.00
+09-Feb-28 - 09-Feb-28 Expenses:Books $20.00 $1620.00
+09-Mar-01 - 09-Mar-01 Expenses:Books $30.00 $1650.00
+09-Mar-31 - 09-Apr-01 Expenses:Books $70.00 $1720.00
+09-Apr-30 - 09-May-01 Expenses:Books $90.00 $1810.00
+09-May-31 - 09-Jun-01 Expenses:Books $110.00 $1920.00
+09-Jun-30 - 09-Jul-01 Expenses:Books $130.00 $2050.00
+09-Jul-31 - 09-Aug-01 Expenses:Books $150.00 $2200.00
+09-Aug-31 - 09-Sep-01 Expenses:Books $170.00 $2370.00
+09-Sep-30 - 09-Oct-01 Expenses:Books $190.00 $2560.00
+09-Oct-31 - 09-Oct-31 Expenses:Books $100.00 $2660.00
+09-Nov-01 - 09-Nov-01 Expenses:Books $110.00 $2770.00
+09-Nov-30 - 09-Dec-01 Expenses:Books $230.00 $3000.00
+09-Dec-31 - 09-Dec-31 Expenses:Books $120.00 $3120.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-exchange.test b/test/baseline/opt-exchange.test
new file mode 100644
index 00000000..9ed46c12
--- /dev/null
+++ b/test/baseline/opt-exchange.test
@@ -0,0 +1,81 @@
+reg --exchange=' C, A '
+<<<
+2009/01/01 January 1st, 2009 (1)
+ Assets:Brokerage 100 A
+ Assets:Brokerage -200 B
+
+2009/01/01 January 1st, 2009 (2)
+ Assets:Brokerage 100 A
+ Assets:Brokerage -300 B
+
+2009/01/01 January 1st, 2009 (3)
+ Assets:Brokerage 100 A
+ Assets:Brokerage -400 B
+
+2009/01/02 January 2nd, 2009
+ Assets:Brokerage 250 B
+ Assets:Brokerage -500 C
+
+2009/01/03 January 3rd, 2009
+ Assets:Brokerage 600 C
+ Assets:Brokerage -1000 D
+
+2009/01/04 January 4th, 2009
+ Assets:Brokerage 300 A
+ Assets:Brokerage -15000 F
+
+2009/01/05 January 5th, 2009
+ Assets:Brokerage 2000 E
+ Assets:Brokerage -8000 F
+
+2009/01/06 January 6th, 2009
+ Assets:Brokerage 155 A @ 2 D
+ Assets:Brokerage
+
+2009/01/07 January 7th, 2009
+ Assets:Brokerage 155 A @@ 200 C
+ Assets:Brokerage
+
+2009/01/08 January 8th, 2009
+ Assets:Brokerage 155 A (A123) @@ 500 F
+ Assets:Brokerage
+
+2009/01/09 January 9th, 2009
+ Assets:Brokerage 1000.00 E
+ Assets:Brokerage -155 A {2 D}
+
+2009/01/10 January 10th, 2009
+ Assets:Brokerage $2,000.00
+ Assets:Brokerage -155 A [2009/01/06]
+>>>1
+09-Jan-01 January 1st, 2009 (1) Assets:Brokerage 100 A 100 A
+ Assets:Brokerage -50 A 50 A
+09-Jan-01 January 1st, 2009 (2) Assets:Brokerage 100 A 150 A
+ Assets:Brokerage -75 A 75 A
+09-Jan-01 January 1st, 2009 (3) Assets:Brokerage 100 A 175 A
+ Assets:Brokerage -100 A 75 A
+09-Jan-02 Commodities revalued <Revalued> 0 600 C
+09-Jan-02 January 2nd, 2009 Assets:Brokerage 500 C 1100 C
+ Assets:Brokerage -500 C 600 C
+09-Jan-03 January 3rd, 2009 Assets:Brokerage 600 C 1200 C
+ Assets:Brokerage -600 C 600 C
+09-Jan-04 January 4th, 2009 Assets:Brokerage 2400 C 3000 C
+ Assets:Brokerage -2400 C 600 C
+09-Jan-05 January 5th, 2009 Assets:Brokerage 1280 C 1880 C
+ Assets:Brokerage -1280 C 600 C
+09-Jan-06 Commodities revalued <Revalued> -2040 C -1440 C
+09-Jan-06 January 6th, 2009 Assets:Brokerage 186 C -1254 C
+ Assets:Brokerage -186 C -1440 C
+09-Jan-07 Commodities revalued <Revalued> -18 C -1458 C
+09-Jan-07 January 7th, 2009 Assets:Brokerage 200 C -1258 C
+ Assets:Brokerage -200 C -1458 C
+09-Jan-08 Commodities revalued <Revalued> -5613 C -7071 C
+09-Jan-08 January 8th, 2009 Assets:Brokerage 200 C -6871 C
+ Assets:Brokerage -200 C -7071 C
+09-Jan-09 Commodities revalued <Revalued> -2800 C -9871 C
+09-Jan-09 January 9th, 2009 Assets:Brokerage 200 C -9671 C
+ Assets:Brokerage -200 C -9871 C
+09-Jan-10 January 10th, 2009 Assets:Brokerage 200 C -9671 C
+ Assets:Brokerage -200 C -9871 C
+>>>2
+=== 0
diff --git a/test/baseline/opt-flat.test b/test/baseline/opt-flat.test
new file mode 100644
index 00000000..6064e833
--- /dev/null
+++ b/test/baseline/opt-flat.test
@@ -0,0 +1,34 @@
+bal --flat
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:One:Books $10.00
+ Expenses:One:Two:Books $10.00
+ Expenses:One:Two:Three:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Assets:Cash
+ Income:Books $-10.00
+
+2008/01/01 January
+ Assets:Cash
+ Income:One:Books $-10.00
+ Income:One:Two:Books $-10.00
+ Income:One:Two:Three:Books $-10.00
+>>>1
+ $10.00 Expenses:Books
+ $10.00 Expenses:One:Books
+ $10.00 Expenses:One:Two:Books
+ $10.00 Expenses:One:Two:Three:Books
+ $-10.00 Income:Books
+ $-10.00 Income:One:Books
+ $-10.00 Income:One:Two:Books
+ $-10.00 Income:One:Two:Three:Books
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-forecast-while.test b/test/baseline/opt-forecast-while.test
new file mode 100644
index 00000000..aebb127f
--- /dev/null
+++ b/test/baseline/opt-forecast-while.test
@@ -0,0 +1,285 @@
+reg --now=2009/03/21 --forecast-while='total < $3500' books
+<<<
+~ monthly
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Expenses:Books $10.00 $10.00
+08-Jan-31 End of January Expenses:Books $10.00 $20.00
+08-Feb-01 February Expenses:Books $20.00 $40.00
+08-Feb-28 End of February Expenses:Books $20.00 $60.00
+08-Mar-01 March Expenses:Books $30.00 $90.00
+08-Mar-31 End of March Expenses:Books $30.00 $120.00
+08-Apr-01 April Expenses:Books $40.00 $160.00
+08-Apr-30 End of April Expenses:Books $40.00 $200.00
+08-May-01 May Expenses:Books $50.00 $250.00
+08-May-31 End of May Expenses:Books $50.00 $300.00
+08-Jun-01 June Expenses:Books $60.00 $360.00
+08-Jun-30 End of June Expenses:Books $60.00 $420.00
+08-Jul-01 July Expenses:Books $70.00 $490.00
+08-Jul-31 End of July Expenses:Books $70.00 $560.00
+08-Aug-01 August Expenses:Books $80.00 $640.00
+08-Aug-31 End of August Expenses:Books $80.00 $720.00
+08-Sep-01 September Expenses:Books $90.00 $810.00
+08-Sep-30 End of September Expenses:Books $90.00 $900.00
+08-Oct-01 October Expenses:Books $100.00 $1000.00
+08-Oct-31 End of October Expenses:Books $100.00 $1100.00
+08-Nov-01 November Expenses:Books $110.00 $1210.00
+08-Nov-30 End of November Expenses:Books $110.00 $1320.00
+08-Dec-01 December Expenses:Books $120.00 $1440.00
+08-Dec-31 End of December Expenses:Books $120.00 $1560.00
+09-Jan-01 January Expenses:Books $10.00 $1570.00
+09-Jan-31 End of January Expenses:Books $10.00 $1580.00
+09-Feb-01 February Expenses:Books $20.00 $1600.00
+09-Feb-28 End of February Expenses:Books $20.00 $1620.00
+09-Mar-01 March Expenses:Books $30.00 $1650.00
+09-Mar-31 End of March Expenses:Books $30.00 $1680.00
+09-Apr-01 April Expenses:Books $40.00 $1720.00
+09-Apr-30 End of April Expenses:Books $40.00 $1760.00
+09-May-01 May Expenses:Books $50.00 $1810.00
+09-May-01 Forecast transaction Expenses:Books $10.00 $1820.00
+09-May-31 End of May Expenses:Books $50.00 $1870.00
+09-Jun-01 June Expenses:Books $60.00 $1930.00
+09-Jun-01 Forecast transaction Expenses:Books $10.00 $1940.00
+09-Jun-30 End of June Expenses:Books $60.00 $2000.00
+09-Jul-01 July Expenses:Books $70.00 $2070.00
+09-Jul-01 Forecast transaction Expenses:Books $10.00 $2080.00
+09-Jul-31 End of July Expenses:Books $70.00 $2150.00
+09-Aug-01 August Expenses:Books $80.00 $2230.00
+09-Aug-01 Forecast transaction Expenses:Books $10.00 $2240.00
+09-Aug-31 End of August Expenses:Books $80.00 $2320.00
+09-Sep-01 September Expenses:Books $90.00 $2410.00
+09-Sep-01 Forecast transaction Expenses:Books $10.00 $2420.00
+09-Sep-30 End of September Expenses:Books $90.00 $2510.00
+09-Oct-01 October Expenses:Books $100.00 $2610.00
+09-Oct-01 Forecast transaction Expenses:Books $10.00 $2620.00
+09-Oct-31 End of October Expenses:Books $100.00 $2720.00
+09-Nov-01 November Expenses:Books $110.00 $2830.00
+09-Nov-01 Forecast transaction Expenses:Books $10.00 $2840.00
+09-Nov-30 End of November Expenses:Books $110.00 $2950.00
+09-Dec-01 December Expenses:Books $120.00 $3070.00
+09-Dec-01 Forecast transaction Expenses:Books $10.00 $3080.00
+09-Dec-31 End of December Expenses:Books $120.00 $3200.00
+10-Jan-01 Forecast transaction Expenses:Books $10.00 $3210.00
+10-Feb-01 Forecast transaction Expenses:Books $10.00 $3220.00
+10-Mar-01 Forecast transaction Expenses:Books $10.00 $3230.00
+10-Apr-01 Forecast transaction Expenses:Books $10.00 $3240.00
+10-May-01 Forecast transaction Expenses:Books $10.00 $3250.00
+10-Jun-01 Forecast transaction Expenses:Books $10.00 $3260.00
+10-Jul-01 Forecast transaction Expenses:Books $10.00 $3270.00
+10-Aug-01 Forecast transaction Expenses:Books $10.00 $3280.00
+10-Sep-01 Forecast transaction Expenses:Books $10.00 $3290.00
+10-Oct-01 Forecast transaction Expenses:Books $10.00 $3300.00
+10-Nov-01 Forecast transaction Expenses:Books $10.00 $3310.00
+10-Dec-01 Forecast transaction Expenses:Books $10.00 $3320.00
+11-Jan-01 Forecast transaction Expenses:Books $10.00 $3330.00
+11-Feb-01 Forecast transaction Expenses:Books $10.00 $3340.00
+11-Mar-01 Forecast transaction Expenses:Books $10.00 $3350.00
+11-Apr-01 Forecast transaction Expenses:Books $10.00 $3360.00
+11-May-01 Forecast transaction Expenses:Books $10.00 $3370.00
+11-Jun-01 Forecast transaction Expenses:Books $10.00 $3380.00
+11-Jul-01 Forecast transaction Expenses:Books $10.00 $3390.00
+11-Aug-01 Forecast transaction Expenses:Books $10.00 $3400.00
+11-Sep-01 Forecast transaction Expenses:Books $10.00 $3410.00
+11-Oct-01 Forecast transaction Expenses:Books $10.00 $3420.00
+11-Nov-01 Forecast transaction Expenses:Books $10.00 $3430.00
+11-Dec-01 Forecast transaction Expenses:Books $10.00 $3440.00
+12-Jan-01 Forecast transaction Expenses:Books $10.00 $3450.00
+12-Feb-01 Forecast transaction Expenses:Books $10.00 $3460.00
+12-Mar-01 Forecast transaction Expenses:Books $10.00 $3470.00
+12-Apr-01 Forecast transaction Expenses:Books $10.00 $3480.00
+12-May-01 Forecast transaction Expenses:Books $10.00 $3490.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-format.test b/test/baseline/opt-format.test
new file mode 100644
index 00000000..9841ea1a
--- /dev/null
+++ b/test/baseline/opt-format.test
@@ -0,0 +1,10 @@
+reg --format='%(account) = %(strip(amount))\n'
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+Assets:Investments:Vanguard:VMMXX = 0.350 VMMXX
+Income:Dividends:Vanguard:VMMXX = $-0.35
+>>>2
+=== 0
diff --git a/test/baseline/opt-gain.test b/test/baseline/opt-gain.test
new file mode 100644
index 00000000..8aeb8bab
--- /dev/null
+++ b/test/baseline/opt-gain.test
@@ -0,0 +1,66 @@
+reg --gain stocks
+<<<
+2009/01/01 Sample 1a
+ Assets:Brokerage:Stocks 100 S
+ Assets:Brokerage:Cash -100 P
+
+P 2009/01/15 00:00:00 S 2 P
+
+2009/02/01 Sample 2a
+ Assets:Brokerage:Stocks 100 S @ 1 P
+ Assets:Brokerage:Cash
+
+P 2009/02/01 00:00:00 S 4 P
+
+2009/03/01 Sample 3a
+ Assets:Brokerage:Stocks 100 S @@ 100 P
+ Assets:Brokerage:Cash
+
+P 2009/03/01 00:00:00 S 8 P
+
+2009/04/01 Sample 4a
+ Assets:Brokerage:Cash 100 P
+ Assets:Brokerage:Stocks -100 S {1 P}
+
+P 2009/04/01 00:00:00 S 16 P
+
+; In this usage case, the top amount is always secondary
+; 2010/01/01 Sample 1b
+; Assets:Brokerage:Cash -100 P
+; Assets:Brokerage:Stocks 100 S
+;
+; P 2010/01/01 00:00:00 S 2 P
+
+2010/02/01 Sample 2b
+ Assets:Brokerage:Cash
+ Assets:Brokerage:Stocks 100 S @ 1 P
+
+P 2010/02/01 00:00:00 S 4 P
+
+2010/03/01 Sample 3b
+ Assets:Brokerage:Cash
+ Assets:Brokerage:Stocks 100 S @@ 100 P
+
+P 2010/03/01 00:00:00 S 8 P
+
+2010/04/01 Sample 4b
+ Assets:Brokerage:Stocks -100 S {1 P}
+ Assets:Brokerage:Cash 100 P
+
+P 2010/04/01 00:00:00 S 16 P
+>>>1
+09-Jan-01 Sample 1a As:Brokerage:Stocks 0 0
+09-Feb-01 Commodities revalued <Revalued> 300 P 300 P
+09-Feb-01 Sample 2a As:Brokerage:Stocks 300 P 600 P
+09-Mar-01 Commodities revalued <Revalued> 800 P 1400 P
+09-Mar-01 Sample 3a As:Brokerage:Stocks 700 P 2100 P
+09-Apr-01 Commodities revalued <Revalued> 2400 P 4500 P
+09-Apr-01 Sample 4a As:Brokerage:Stocks -1500 P 3000 P
+10-Feb-01 Commodities revalued <Revalued> -2400 P 600 P
+10-Feb-01 Sample 2b As:Brokerage:Stocks 300 P 900 P
+10-Mar-01 Commodities revalued <Revalued> 1200 P 2100 P
+10-Mar-01 Sample 3b As:Brokerage:Stocks 700 P 2800 P
+10-Apr-01 Commodities revalued <Revalued> 3200 P 6000 P
+10-Apr-01 Sample 4b As:Brokerage:Stocks -1500 P 4500 P
+>>>2
+=== 0
diff --git a/test/baseline/opt-head.test b/test/baseline/opt-head.test
new file mode 100644
index 00000000..eeca0b12
--- /dev/null
+++ b/test/baseline/opt-head.test
@@ -0,0 +1,206 @@
+reg --head=10 books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Expenses:Books $10.00 $10.00
+08-Jan-31 End of January Expenses:Books $10.00 $20.00
+08-Feb-01 February Expenses:Books $20.00 $40.00
+08-Feb-28 End of February Expenses:Books $20.00 $60.00
+08-Mar-01 March Expenses:Books $30.00 $90.00
+08-Mar-31 End of March Expenses:Books $30.00 $120.00
+08-Apr-01 April Expenses:Books $40.00 $160.00
+08-Apr-30 End of April Expenses:Books $40.00 $200.00
+08-May-01 May Expenses:Books $50.00 $250.00
+08-May-31 End of May Expenses:Books $50.00 $300.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-input-date-format.test b/test/baseline/opt-input-date-format.test
new file mode 100644
index 00000000..0ab5e5c9
--- /dev/null
+++ b/test/baseline/opt-input-date-format.test
@@ -0,0 +1,11 @@
+reg --input-date-format='%m%%%d%%%Y'
+<<<
+02%02%2007 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-invert.test b/test/baseline/opt-invert.test
new file mode 100644
index 00000000..9a9f6d02
--- /dev/null
+++ b/test/baseline/opt-invert.test
@@ -0,0 +1,11 @@
+reg --invert
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX -0.350 VMMXX -0.350 VMMXX
+ In:Di:Vanguard:VMMXX $0.35 $0.35
+ -0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-limit.test b/test/baseline/opt-limit.test
new file mode 100644
index 00000000..dd302d1b
--- /dev/null
+++ b/test/baseline/opt-limit.test
@@ -0,0 +1,212 @@
+reg --limit='account =~ /Books/ and amount < 50'
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Expenses:Books $10.00 $10.00
+08-Jan-31 End of January Expenses:Books $10.00 $20.00
+08-Feb-01 February Expenses:Books $20.00 $40.00
+08-Feb-28 End of February Expenses:Books $20.00 $60.00
+08-Mar-01 March Expenses:Books $30.00 $90.00
+08-Mar-31 End of March Expenses:Books $30.00 $120.00
+08-Apr-01 April Expenses:Books $40.00 $160.00
+08-Apr-30 End of April Expenses:Books $40.00 $200.00
+09-Jan-01 January Expenses:Books $10.00 $210.00
+09-Jan-31 End of January Expenses:Books $10.00 $220.00
+09-Feb-01 February Expenses:Books $20.00 $240.00
+09-Feb-28 End of February Expenses:Books $20.00 $260.00
+09-Mar-01 March Expenses:Books $30.00 $290.00
+09-Mar-31 End of March Expenses:Books $30.00 $320.00
+09-Apr-01 April Expenses:Books $40.00 $360.00
+09-Apr-30 End of April Expenses:Books $40.00 $400.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-lot-dates.test b/test/baseline/opt-lot-dates.test
new file mode 100644
index 00000000..2415fb27
--- /dev/null
+++ b/test/baseline/opt-lot-dates.test
@@ -0,0 +1,4497 @@
+reg -F '%(justify(scrub(total_expr), 80, 80, true))\n' --lot-dates --unsorted
+<<<
+C 1.00s = 100c
+C 1.00G = 100s
+
+D 1.00G
+
+2006/03/14 Opening Balances
+ Assets:Tajer 1339829c
+ Assets:Gruulmorg 248720c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1428c
+ Expenses:Fees:Auction 768c
+ Expenses:Fees:Auction 612c
+ Expenses:Fees:Auction 4764c
+ Expenses:Fees:Auction 3372c
+ Expenses:Fees:Auction 1296c
+ Expenses:Fees:Auction 1332c
+ Expenses:Fees:Auction 660c
+ Expenses:Fees:Auction 10044c
+ Expenses:Fees:Auction 3588c
+ Expenses:Fees:Auction 1632c
+ Expenses:Fees:Auction 8388c
+ Expenses:Fees:Auction 9984c
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 158860c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1320c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 11496c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 3216c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/14 Auction House
+ Assets:Tajer 34678c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Gruulmorg 1G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Assets:Tajer 59389c
+ Equity:Gold
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/14 Player
+ Assets:Tajer 6G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Items 35s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer:Items "Plans: Wildthorn Mail" 1 @ 125s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Bids 259c
+ Assets:Bids 45s
+ Assets:Bids 4720c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Expenses:Items 8G
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Puldoost
+ Assets:Tajer 8G
+ Expenses:Items
+
+2006/03/14 Auction House
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" 1 {1.25G}
+ Assets:Tajer:Items
+
+2006/03/15 Auction House
+ Assets:Tajer 45s
+ Assets:Tajer 259c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Assets:Tajer 4720c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 12542c ; something got lost here
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 2375c
+ Expenses:Fees:Auction -2375c
+ Assets:Gruulmorg
+
+2006/03/15 Auction House
+ Assets:Danell 4c
+ Equity:Gold
+
+2006/03/15 Transfer
+ Assets:Gruulmorg 2c
+ Assets:Danell
+
+2006/03/15 Transfer
+ Assets:Danell 4250c
+ Expenses:Fees:Auction 750c
+ Assets:Gruulmorg -50s
+
+2006/03/15 Post
+ Expenses:Fees:Mail 60c
+ Assets:Danell
+
+2006/03/15 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/15 Post
+ Assets:Wyshona 40s
+ Expenses:Fees:Mail 30c
+ Assets:Danell
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8s
+ Expenses:Fees:Auction 11s
+ Assets:Wyshona
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Beaststalker's Belt" 1 @ 65G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Vendor
+ Assets:Tajer 16744c
+ Assets:Tajer 16640c
+ Equity:Gold
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 772c
+ Expenses:Fees:Auction 544c
+ Expenses:Fees:Auction 444c
+ Expenses:Fees:Auction 432c
+ Expenses:Fees:Auction 204c
+ Assets:Tajer
+
+2006/03/15 Player
+ Assets:Tajer 12s
+ Equity:Gold
+
+2006/03/15 Vendor
+ Assets:Tajer 22s
+ Equity:Gold
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 1G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 21050c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 23000c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 150s
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/16 Post
+ Expenses:Fees:Mail 90c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 1195768c
+ Assets:Tajer:Items "Beaststalker's Belt" -1 {65G} @ 1195768c
+ Income:Brokering -545768c
+
+2006/03/16 Auction House
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {21050c}
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {2.3G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1.5G}
+ Assets:Tajer:Items
+
+2006/03/16 Player
+ Assets:Tajer 4G
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Wyshona 1341s
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Gruulmorg 4c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 4c
+ Expenses:Fees:Mail 120c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 24s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 84c
+ Expenses:Fees:Auction 84c
+ Assets:Wyshona
+
+2006/03/16 Crazy Cat Lady
+ Expenses:Items 40s
+ Expenses:Items 40s
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 60c
+ Assets:Danell 5G
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Tajer 20G
+ Assets:Gruulmorg
+
+2006/03/16 Auction House
+ Assets:Tajer:Items "Pulsating Hydra Heart" 1 @ 1G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 936c
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg 30G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Gruulmorg:Items "Ace of Warlords" 2 @ 15G
+ Assets:Gruulmorg
+
+2006/03/16 Transfer
+ Assets:Tajer:Items "Ace of Warlords" 2 {15G}
+ Assets:Gruulmorg:Items
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 2104c
+ Equity:Gold
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Assets:Danell 6c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/16 General Goods Vendor
+ Expenses:Items 50c ; wrapping paper
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 1G
+ Equity:Gold
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1.5G} @ 180584c
+ Income:Brokering -165584c
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1G} @ 180584c
+ Income:Brokering -170584c
+
+2006/03/17 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Player: raev
+ Assets:Tajer:Items "Wildheart Belt" 1 {30G}
+ Assets:Tajer:Items "Ace of Warlords" -2 {15G}
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 7482c
+ Assets:Tajer
+
+2006/03/17 Post
+ Expenses:Fees:Mail 300c
+ Assets:Wyshona
+
+2006/03/17 Player
+ Assets:Wyshona 1G
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" -1 {1.25G} @ 1G
+ Expenses:Capital Loss 25s
+
+2006/03/17 Auction House (implicit transfer)
+ Expenses:Items 279s ; Recipe: Swiftness Potion
+ Assets:Wyshona
+
+2006/03/17 Auction House (implicit transfer)
+ Assets:Danell:Items "Ace of Warlords" 1 @ 3G
+ Assets:Tajer:Items "Ace of Warlords" 1 @ 3.9G
+ Assets:Tajer:Items "Holy Bologna" 1 @ 2G
+ Assets:Tajer:Items "The Emerald Dream" 1 @ 4G
+ Assets:Tajer:Items "The Arcanist's Cookbook" 1 @ 4G
+ Assets:Tajer:Items "Harnessing Shadows" 1 @ 5G
+ Assets:Tajer:Items "Garona: Book on Treachery" 1 @ 4G
+ Assets:Tajer:Items "Preserved Holly" 5 @ 20s
+ Assets:Wyshona
+
+2006/03/17 Auction House
+ Assets:Tajer 4G
+ Assets:Tajer:Items "Pulsating Hydra Heart" -1 {1G} @ 4G
+ Income:Brokering -3G
+
+2006/03/17 Auction House
+ Assets:Danell 3171c
+ Assets:Danell:Items "Ace of Warlords" -1 {3G} @ 3171c
+ Expenses:Capital Loss 26829c
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 12537c
+ Assets:Danell
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 15G
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Auction House
+ Assets:Wyshona 362450c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {21050c} @ 181225c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {2.3G} @ 181225c
+ Income:Brokering -318400c
+
+2006/03/17 Transfer
+ Assets:Danell 499560c
+ Expenses:Gifts 1G
+ Expenses:Fees:Mail 30c
+ Assets:Wyshona
+
+2006/03/17 Post
+ Expenses:Fees:Mail 90c
+ Expenses:Fees:Auction 166c
+ Assets:Gruulmorg
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 459211c
+ Expenses:Fees:Auction 81023c
+ Assets:Danell -540234c
+
+2006/03/17 Transfer
+ Assets:Tajer 662465c
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/18 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "Ace of Warlords" -1 {3.9G} @ 15G
+ Income:Brokering -111000c
+
+2006/03/18 Auction House
+ Assets:Tajer 434472c
+ Assets:Tajer:Items "Wildheart Belt" -1 {30G} @ 434472c
+ Income:Brokering -134472c
+
+2006/03/18 Auction House
+ Assets:Tajer 1995s
+ Assets:Tajer:Items "Harnessing Shadows" -1 {5G} @ 1995s
+ Income:Brokering -1495s
+
+2006/03/19 Auction House
+ Assets:Tajer 2850s
+ Assets:Tajer:Items "Garona: Book on Treachery" -1 {4G} @ 2850s
+ Income:Brokering -2450s
+
+2006/03/19 Auction House
+ Assets:Tajer 1710s
+ Assets:Tajer:Items "The Arcanist's Cookbook" -1 {4G} @ 1710s
+ Income:Brokering -1310s
+
+2006/03/19 Auction House
+ Assets:Tajer 46550c
+ Assets:Tajer:Items "Preserved Holly" -5 {20s} @ 9310c
+ Income:Brokering -36550c
+
+2006/03/19 Auction House
+ Assets:Tajer:Items "Two of Portals" 1 @ 3G
+ Assets:Tajer:Items "Two of Portals" 1 @ 2.5G
+ Assets:Tajer
+
+2006/03/20 Auction House
+ Assets:Tajer 163443c
+ Assets:Tajer:Items "Holy Bologna" -1 {2G} @ 163443c
+ Income:Brokering -143443c
+
+2006/03/20 Auction House
+ Assets:Tajer 5G
+ Assets:Tajer:Items "Two of Portals" -1 {3G} @ 5G
+ Income:Brokering -2G
+
+2006/03/20 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "The Emerald Dream" -1 {4G} @ 15G
+ Income:Brokering -11G
+
+2006/03/20 Auction House
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 170G
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Expenses:Fees:Auction 2760c
+ Expenses:Fees:Auction 2760c
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Assets:Tajer:Items "Nightblade" 1 @ 200G
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/23 Auction House
+ Assets:Tajer 1665260c
+ Assets:Tajer:Items "Orb of Deception" -1 {170G} @ 1665260c
+ Expenses:Capital Loss 34740c
+
+2006/03/26 Auction House
+ Assets:Tajer 81980c
+ Assets:Tajer:Items "Two of Portals" -1 {2.5G} @ 81980c
+ Income:Brokering -56980c
+
+2006/03/26 Player
+ Expenses:Items 150s ; Recipe: Elixir of Minor Agility
+ Expenses:Fees:Mail 30c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/27 Player
+ Assets:Tajer 160G
+ Assets:Tajer:Items "Nightblade" -1 {200G} @ 160G
+ Expenses:Capital Loss 40G
+
+2006/03/27 Player
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/26 Player
+ Expenses:Items (9G * 6) ; Traveler's backpacks
+ Expenses:Items 10G
+ Expenses:Fees:Bank 10G
+ Expenses:Fees:Mail 630c
+ Expenses:Fees:Mail 330c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/04/01 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 155G
+ Assets:Tajer
+>>>1
+ 133.98G
+ 158.85G
+ 0
+ 14.28s
+ 21.96s
+ 28.08s
+ 75.72s
+ 1.09G
+ 1.22G
+ 1.36G
+ 1.42G
+ 2.43G
+ 2.79G
+ 2.95G
+ 3.79G
+ 4.79G
+ 5.02G
+ 0
+ 15.89G
+ 0
+ 13.20s
+ 0
+ 1.15G
+ 0
+ 32.16s
+ 0
+ 30c
+ 0
+ 3.47G
+ 0
+ 23.16s
+ 0
+ 1.00G
+ 0
+ 5.94G
+ 0
+ 1.20s
+ 0
+ 3.00G
+ 0
+ 6.00G
+ 0
+ 35.00s
+ 0
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -1.22G
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -77.41s
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -30.21s
+ -1.25G
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -1.24G
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ 6.75G
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -1.24G
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ 6.75G
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.05G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.02G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.03G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.26G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.08G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.00G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.49G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ 50.00s
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.10G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.10G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.42G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.31G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -2.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -66.67G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -65.83G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -64.16G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.42G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.37G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.32G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.28G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.26G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.38G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.28G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 1 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -68.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 1 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -68.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 1 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -68.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 1 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -67.67G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 1 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -68.50G
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 1 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -68.50G
+ "Plans: Mithril Shield Spike" 1 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 1 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -70.61G
+ "Plans: Mithril Shield Spike" 1 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 1 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -70.61G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 1 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -72.90G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 1 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -72.90G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -74.40G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -71.40G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -74.40G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -74.40G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -74.40G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 45.17G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 45.17G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -9.40G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 45.17G
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 45.17G
+ "Plans: Mithril Shield Spike" 1
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 45.17G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 45.17G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 1
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 45.17G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 42.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 51.68G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.28G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.51G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.63G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.75G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.76G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.76G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.67G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 39.07G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 43.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 58.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 38.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 37.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 37.36G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 37.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 37.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 67.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 37.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 37.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 7.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 7.27G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.72G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.52G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -21.98G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -21.23G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -21.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -22.73G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -4.67G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -4.67G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -21.23G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -4.67G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 13.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 13.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -3.67G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 13.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 13.39G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 13.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Ace of Warlords" 2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 13.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 13.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.13G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 13.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 13.41G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 13.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.63G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 17.17G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 1 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 14.38G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -12.52G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -8.52G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -8.52G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -11.52G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -8.52G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -8.20G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -8.20G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -5.52G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -8.20G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -6.95G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -8.20G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 6.80G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 6.80G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -8.20G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 1
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -3.79G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 12.22G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 78.00G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 79.00G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 79.00G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.07G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 73.97G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 82.07G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 94.29G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 94.30G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.80G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.80G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 28.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -1
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 43.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 43.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 31.95G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 43.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 86.49G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Wildheart Belt" 1
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 86.49G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 73.05G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 86.49G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 106.44G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 106.44G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 91.49G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 106.44G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 134.94G
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 134.94G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 110.44G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 134.94G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 152.04G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 152.04G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 138.94G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 152.04G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 156.70G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 156.70G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 153.04G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 156.70G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 156.70G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" 1 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 156.70G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 151.20G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 167.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 167.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 153.20G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 167.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 172.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 172.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 170.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 172.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 187.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 187.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 176.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 187.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 187.55G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 187.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 187.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 17.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 17.82G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 18.09G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 17.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 17.54G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -182.46G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -180.69G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -178.92G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -177.15G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -175.38G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -174.63G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -182.46G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -15.93G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -15.93G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -12.46G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -15.93G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -7.73G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -1
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -7.73G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -13.43G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -7.73G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -6.23G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -6.23G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -6.23G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -7.73G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 152.27G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 152.27G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 192.27G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 152.27G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 152.27G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 152.27G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 206.27G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 216.27G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 226.27G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 226.33G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 226.36G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 226.37G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 152.27G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ 152.27G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Orb of Deception" 1 [2006/04/01]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+ "Ace of Warlords" -2
+ "Ace of Warlords" 2 [2006/03/16]
+ "Ace of Warlords" 2 [2006/03/17]
+ "Beaststalker's Belt" -1
+ "Beaststalker's Belt" 1 [2006/03/15]
+ -2.73G
+ "Garona: Book on Treachery" -1
+ "Garona: Book on Treachery" 1 [2006/03/17]
+ "Harnessing Shadows" -1
+ "Harnessing Shadows" 1 [2006/03/17]
+ "Holy Bologna" -1
+ "Holy Bologna" 1 [2006/03/17]
+ Nightblade -1
+ Nightblade 1 [2006/03/22]
+ "Orb of Deception" -1
+ "Orb of Deception" 1 [2006/03/21]
+ "Orb of Deception" 1 [2006/04/01]
+ "Plans: Mithril Shield Spike" 2 [2006/03/15]
+ "Plans: Wildthorn Mail" 1 [2006/03/14]
+ "Preserved Holly" -5
+ "Preserved Holly" 5 [2006/03/17]
+ "Pulsating Hydra Heart" -1
+ "Pulsating Hydra Heart" 1 [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 2 [2006/03/15]
+ "The Arcanist's Cookbook" -1
+ "The Arcanist's Cookbook" 1 [2006/03/17]
+ "The Emerald Dream" -1
+ "The Emerald Dream" 1 [2006/03/17]
+ "Two of Portals" -2
+ "Two of Portals" 2 [2006/03/19]
+>>>2
+=== 0
diff --git a/test/baseline/opt-lot-prices.test b/test/baseline/opt-lot-prices.test
new file mode 100644
index 00000000..22aa5ab5
--- /dev/null
+++ b/test/baseline/opt-lot-prices.test
@@ -0,0 +1,2891 @@
+reg -F '%(justify(scrub(total_expr), 80, 80, true))\n' --lot-prices --unsorted
+<<<
+C 1.00s = 100c
+C 1.00G = 100s
+
+D 1.00G
+
+2006/03/14 Opening Balances
+ Assets:Tajer 1339829c
+ Assets:Gruulmorg 248720c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1428c
+ Expenses:Fees:Auction 768c
+ Expenses:Fees:Auction 612c
+ Expenses:Fees:Auction 4764c
+ Expenses:Fees:Auction 3372c
+ Expenses:Fees:Auction 1296c
+ Expenses:Fees:Auction 1332c
+ Expenses:Fees:Auction 660c
+ Expenses:Fees:Auction 10044c
+ Expenses:Fees:Auction 3588c
+ Expenses:Fees:Auction 1632c
+ Expenses:Fees:Auction 8388c
+ Expenses:Fees:Auction 9984c
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 158860c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1320c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 11496c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 3216c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/14 Auction House
+ Assets:Tajer 34678c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Gruulmorg 1G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Assets:Tajer 59389c
+ Equity:Gold
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/14 Player
+ Assets:Tajer 6G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Items 35s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer:Items "Plans: Wildthorn Mail" 1 @ 125s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Bids 259c
+ Assets:Bids 45s
+ Assets:Bids 4720c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Expenses:Items 8G
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Puldoost
+ Assets:Tajer 8G
+ Expenses:Items
+
+2006/03/14 Auction House
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" 1 {1.25G}
+ Assets:Tajer:Items
+
+2006/03/15 Auction House
+ Assets:Tajer 45s
+ Assets:Tajer 259c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Assets:Tajer 4720c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 12542c ; something got lost here
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 2375c
+ Expenses:Fees:Auction -2375c
+ Assets:Gruulmorg
+
+2006/03/15 Auction House
+ Assets:Danell 4c
+ Equity:Gold
+
+2006/03/15 Transfer
+ Assets:Gruulmorg 2c
+ Assets:Danell
+
+2006/03/15 Transfer
+ Assets:Danell 4250c
+ Expenses:Fees:Auction 750c
+ Assets:Gruulmorg -50s
+
+2006/03/15 Post
+ Expenses:Fees:Mail 60c
+ Assets:Danell
+
+2006/03/15 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/15 Post
+ Assets:Wyshona 40s
+ Expenses:Fees:Mail 30c
+ Assets:Danell
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8s
+ Expenses:Fees:Auction 11s
+ Assets:Wyshona
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Beaststalker's Belt" 1 @ 65G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Vendor
+ Assets:Tajer 16744c
+ Assets:Tajer 16640c
+ Equity:Gold
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 772c
+ Expenses:Fees:Auction 544c
+ Expenses:Fees:Auction 444c
+ Expenses:Fees:Auction 432c
+ Expenses:Fees:Auction 204c
+ Assets:Tajer
+
+2006/03/15 Player
+ Assets:Tajer 12s
+ Equity:Gold
+
+2006/03/15 Vendor
+ Assets:Tajer 22s
+ Equity:Gold
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 1G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 21050c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 23000c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 150s
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/16 Post
+ Expenses:Fees:Mail 90c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 1195768c
+ Assets:Tajer:Items "Beaststalker's Belt" -1 {65G} @ 1195768c
+ Income:Brokering -545768c
+
+2006/03/16 Auction House
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {21050c}
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {2.3G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1.5G}
+ Assets:Tajer:Items
+
+2006/03/16 Player
+ Assets:Tajer 4G
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Wyshona 1341s
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Gruulmorg 4c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 4c
+ Expenses:Fees:Mail 120c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 24s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 84c
+ Expenses:Fees:Auction 84c
+ Assets:Wyshona
+
+2006/03/16 Crazy Cat Lady
+ Expenses:Items 40s
+ Expenses:Items 40s
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 60c
+ Assets:Danell 5G
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Tajer 20G
+ Assets:Gruulmorg
+
+2006/03/16 Auction House
+ Assets:Tajer:Items "Pulsating Hydra Heart" 1 @ 1G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 936c
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg 30G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Gruulmorg:Items "Ace of Warlords" 2 @ 15G
+ Assets:Gruulmorg
+
+2006/03/16 Transfer
+ Assets:Tajer:Items "Ace of Warlords" 2 {15G}
+ Assets:Gruulmorg:Items
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 2104c
+ Equity:Gold
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Assets:Danell 6c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/16 General Goods Vendor
+ Expenses:Items 50c ; wrapping paper
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 1G
+ Equity:Gold
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1.5G} @ 180584c
+ Income:Brokering -165584c
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1G} @ 180584c
+ Income:Brokering -170584c
+
+2006/03/17 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Player: raev
+ Assets:Tajer:Items "Wildheart Belt" 1 {30G}
+ Assets:Tajer:Items "Ace of Warlords" -2 {15G}
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 7482c
+ Assets:Tajer
+
+2006/03/17 Post
+ Expenses:Fees:Mail 300c
+ Assets:Wyshona
+
+2006/03/17 Player
+ Assets:Wyshona 1G
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" -1 {1.25G} @ 1G
+ Expenses:Capital Loss 25s
+
+2006/03/17 Auction House (implicit transfer)
+ Expenses:Items 279s ; Recipe: Swiftness Potion
+ Assets:Wyshona
+
+2006/03/17 Auction House (implicit transfer)
+ Assets:Danell:Items "Ace of Warlords" 1 @ 3G
+ Assets:Tajer:Items "Ace of Warlords" 1 @ 3.9G
+ Assets:Tajer:Items "Holy Bologna" 1 @ 2G
+ Assets:Tajer:Items "The Emerald Dream" 1 @ 4G
+ Assets:Tajer:Items "The Arcanist's Cookbook" 1 @ 4G
+ Assets:Tajer:Items "Harnessing Shadows" 1 @ 5G
+ Assets:Tajer:Items "Garona: Book on Treachery" 1 @ 4G
+ Assets:Tajer:Items "Preserved Holly" 5 @ 20s
+ Assets:Wyshona
+
+2006/03/17 Auction House
+ Assets:Tajer 4G
+ Assets:Tajer:Items "Pulsating Hydra Heart" -1 {1G} @ 4G
+ Income:Brokering -3G
+
+2006/03/17 Auction House
+ Assets:Danell 3171c
+ Assets:Danell:Items "Ace of Warlords" -1 {3G} @ 3171c
+ Expenses:Capital Loss 26829c
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 12537c
+ Assets:Danell
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 15G
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Auction House
+ Assets:Wyshona 362450c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {21050c} @ 181225c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {2.3G} @ 181225c
+ Income:Brokering -318400c
+
+2006/03/17 Transfer
+ Assets:Danell 499560c
+ Expenses:Gifts 1G
+ Expenses:Fees:Mail 30c
+ Assets:Wyshona
+
+2006/03/17 Post
+ Expenses:Fees:Mail 90c
+ Expenses:Fees:Auction 166c
+ Assets:Gruulmorg
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 459211c
+ Expenses:Fees:Auction 81023c
+ Assets:Danell -540234c
+
+2006/03/17 Transfer
+ Assets:Tajer 662465c
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/18 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "Ace of Warlords" -1 {3.9G} @ 15G
+ Income:Brokering -111000c
+
+2006/03/18 Auction House
+ Assets:Tajer 434472c
+ Assets:Tajer:Items "Wildheart Belt" -1 {30G} @ 434472c
+ Income:Brokering -134472c
+
+2006/03/18 Auction House
+ Assets:Tajer 1995s
+ Assets:Tajer:Items "Harnessing Shadows" -1 {5G} @ 1995s
+ Income:Brokering -1495s
+
+2006/03/19 Auction House
+ Assets:Tajer 2850s
+ Assets:Tajer:Items "Garona: Book on Treachery" -1 {4G} @ 2850s
+ Income:Brokering -2450s
+
+2006/03/19 Auction House
+ Assets:Tajer 1710s
+ Assets:Tajer:Items "The Arcanist's Cookbook" -1 {4G} @ 1710s
+ Income:Brokering -1310s
+
+2006/03/19 Auction House
+ Assets:Tajer 46550c
+ Assets:Tajer:Items "Preserved Holly" -5 {20s} @ 9310c
+ Income:Brokering -36550c
+
+2006/03/19 Auction House
+ Assets:Tajer:Items "Two of Portals" 1 @ 3G
+ Assets:Tajer:Items "Two of Portals" 1 @ 2.5G
+ Assets:Tajer
+
+2006/03/20 Auction House
+ Assets:Tajer 163443c
+ Assets:Tajer:Items "Holy Bologna" -1 {2G} @ 163443c
+ Income:Brokering -143443c
+
+2006/03/20 Auction House
+ Assets:Tajer 5G
+ Assets:Tajer:Items "Two of Portals" -1 {3G} @ 5G
+ Income:Brokering -2G
+
+2006/03/20 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "The Emerald Dream" -1 {4G} @ 15G
+ Income:Brokering -11G
+
+2006/03/20 Auction House
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 170G
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Expenses:Fees:Auction 2760c
+ Expenses:Fees:Auction 2760c
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Assets:Tajer:Items "Nightblade" 1 @ 200G
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/23 Auction House
+ Assets:Tajer 1665260c
+ Assets:Tajer:Items "Orb of Deception" -1 {170G} @ 1665260c
+ Expenses:Capital Loss 34740c
+
+2006/03/26 Auction House
+ Assets:Tajer 81980c
+ Assets:Tajer:Items "Two of Portals" -1 {2.5G} @ 81980c
+ Income:Brokering -56980c
+
+2006/03/26 Player
+ Expenses:Items 150s ; Recipe: Elixir of Minor Agility
+ Expenses:Fees:Mail 30c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/27 Player
+ Assets:Tajer 160G
+ Assets:Tajer:Items "Nightblade" -1 {200G} @ 160G
+ Expenses:Capital Loss 40G
+
+2006/03/27 Player
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/26 Player
+ Expenses:Items (9G * 6) ; Traveler's backpacks
+ Expenses:Items 10G
+ Expenses:Fees:Bank 10G
+ Expenses:Fees:Mail 630c
+ Expenses:Fees:Mail 330c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/04/01 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 155G
+ Assets:Tajer
+>>>1
+ 133.98G
+ 158.85G
+ 0
+ 14.28s
+ 21.96s
+ 28.08s
+ 75.72s
+ 1.09G
+ 1.22G
+ 1.36G
+ 1.42G
+ 2.43G
+ 2.79G
+ 2.95G
+ 3.79G
+ 4.79G
+ 5.02G
+ 0
+ 15.89G
+ 0
+ 13.20s
+ 0
+ 1.15G
+ 0
+ 32.16s
+ 0
+ 30c
+ 0
+ 3.47G
+ 0
+ 23.16s
+ 0
+ 1.00G
+ 0
+ 5.94G
+ 0
+ 1.20s
+ 0
+ 3.00G
+ 0
+ 6.00G
+ 0
+ 35.00s
+ 0
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -1.22G
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -77.41s
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -30.21s
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -1.24G
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ 6.75G
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -1.24G
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ 6.75G
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -1.25G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.05G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.02G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.03G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -1.25G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.26G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.08G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.00G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.49G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ 50.00s
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.10G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.10G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.42G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.31G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -2.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -66.67G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -65.83G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -64.16G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.42G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.37G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.32G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.28G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.26G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.38G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.28G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -68.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -68.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -68.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -67.67G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -68.50G
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -68.50G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -70.61G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -70.61G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -72.90G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -72.90G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -74.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -71.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -74.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -74.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G}
+ -74.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ -9.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 42.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 51.68G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.28G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.51G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.63G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.75G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.76G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.76G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.67G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 39.07G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 43.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 58.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 37.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 37.36G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 37.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 37.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 67.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ 37.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 37.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 7.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ 7.27G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.72G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.52G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -21.98G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -21.23G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -21.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -4.67G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -4.67G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -21.23G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -4.67G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 2 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ -3.67G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ 13.39G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 4 {15.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.13G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 13.41G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 2 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.63G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 17.17G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 14.38G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -12.52G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -8.52G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -8.52G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -11.52G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -8.52G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -8.20G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -8.20G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -5.52G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -8.20G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -6.95G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -8.20G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 6.80G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 6.80G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -8.20G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 2 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 2 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ -3.79G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 12.22G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 78.00G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 79.00G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 79.00G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.07G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 73.97G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 82.07G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 94.29G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 94.30G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.80G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.80G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.90G}
+ "Ace of Warlords" 2 {15.00G}
+ 43.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 43.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 31.95G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 43.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 86.49G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 86.49G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 73.05G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 86.49G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 106.44G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 106.44G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 91.49G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 106.44G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 134.94G
+ "Garona: Book on Treachery" 1 {4.00G}
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 134.94G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 110.44G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 134.94G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 152.04G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Arcanist's Cookbook" 1 {4.00G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 152.04G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 138.94G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 152.04G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 156.70G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Preserved Holly" 5 {20.00s}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 156.70G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 153.04G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 156.70G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 156.70G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {3.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 156.70G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {2.50G}
+ "Two of Portals" 1 {3.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 151.20G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {2.50G}
+ "Two of Portals" 1 {3.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 167.54G
+ "Holy Bologna" 1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {2.50G}
+ "Two of Portals" 1 {3.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 167.54G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {2.50G}
+ "Two of Portals" 1 {3.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 153.20G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {2.50G}
+ "Two of Portals" 1 {3.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 167.54G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {2.50G}
+ "Two of Portals" 1 {3.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 172.54G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {2.50G}
+ "Two of Portals" 1 {3.00G}
+ "Ace of Warlords" 2 {15.00G}
+ 172.54G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 170.54G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 172.54G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 187.54G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "The Emerald Dream" 1 {4.00G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 187.54G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 176.54G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 187.54G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 187.55G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 187.54G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 187.54G
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 17.54G
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 17.82G
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 18.09G
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 17.54G
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 17.54G
+ Nightblade 1 {200.00G}
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -182.46G
+ Nightblade 1 {200.00G}
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -180.69G
+ Nightblade 1 {200.00G}
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -178.92G
+ Nightblade 1 {200.00G}
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -177.15G
+ Nightblade 1 {200.00G}
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -175.38G
+ Nightblade 1 {200.00G}
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -174.63G
+ Nightblade 1 {200.00G}
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -182.46G
+ Nightblade 1 {200.00G}
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -15.93G
+ Nightblade 1 {200.00G}
+ "Orb of Deception" 1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -15.93G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -12.46G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -15.93G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -7.73G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Two of Portals" 1 {2.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -7.73G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -13.43G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -7.73G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -6.23G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -6.23G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -6.23G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -7.73G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 152.27G
+ Nightblade 1 {200.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 152.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 192.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 152.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 152.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 152.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 206.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 216.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 226.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 226.33G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 226.36G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 226.37G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 152.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ 152.27G
+ "Orb of Deception" 1 {155.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G}
+ -2.73G
+ "Orb of Deception" 1 {155.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+>>>2
+=== 0
diff --git a/test/baseline/opt-lot-tags.test b/test/baseline/opt-lot-tags.test
new file mode 100644
index 00000000..d77aea33
--- /dev/null
+++ b/test/baseline/opt-lot-tags.test
@@ -0,0 +1,12 @@
+bal --lot-tags tajer
+<<<
+D 1.00c
+
+2006/03/14 Opening Balances
+ Assets:Tajer 1339829c (TAG)
+ Assets:Gruulmorg 248720c
+ Equity:Gold
+>>>1
+ 1339829.00c (TAG) Assets:Tajer
+>>>2
+=== 0
diff --git a/test/baseline/opt-lots-actual.test b/test/baseline/opt-lots-actual.test
new file mode 100644
index 00000000..39a27363
--- /dev/null
+++ b/test/baseline/opt-lots-actual.test
@@ -0,0 +1,27 @@
+reg --format '%(justify(scrub(total_expr), 40, 40, true))\n' --lots
+<<<
+D 1.0000s
+
+2006/03/14 Opening Balances
+ Assets:Tajer 1339829c @ 1.86590975416s
+ Assets:Gruulmorg 248720c {10.051463493s}
+ Equity:Gold -5000000s
+>>>1
+ 1339829c {1.8659s} [2006/03/14]
+ 1339829c {1.8659s} [2006/03/14]
+ 248720c {10.0515s}
+ 1339829c {1.8659s} [2006/03/14]
+ 248720c {10.0515s}
+ -1388.9h
+>>>2
+=== 0
+reg --format '%(justify(scrub(total_expr), 40, 40, true))\n' --lots-actual
+>>>1
+ 1339829c
+ 1339829c
+ 248720c {10.0515s}
+ 1339829c
+ 248720c {10.0515s}
+ -1388.9h
+>>>2
+=== 0
diff --git a/test/baseline/opt-lots.test b/test/baseline/opt-lots.test
new file mode 100644
index 00000000..916a2b2e
--- /dev/null
+++ b/test/baseline/opt-lots.test
@@ -0,0 +1,5373 @@
+reg -F '%(justify(scrub(total_expr), 80, 80, true))\n' --lots --unsorted
+<<<
+C 1.00s = 100c
+C 1.00G = 100s
+
+D 1.00G
+
+2006/03/14 Opening Balances
+ Assets:Tajer 1339829c
+ Assets:Gruulmorg 248720c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1428c
+ Expenses:Fees:Auction 768c
+ Expenses:Fees:Auction 612c
+ Expenses:Fees:Auction 4764c
+ Expenses:Fees:Auction 3372c
+ Expenses:Fees:Auction 1296c
+ Expenses:Fees:Auction 1332c
+ Expenses:Fees:Auction 660c
+ Expenses:Fees:Auction 10044c
+ Expenses:Fees:Auction 3588c
+ Expenses:Fees:Auction 1632c
+ Expenses:Fees:Auction 8388c
+ Expenses:Fees:Auction 9984c
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 158860c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1320c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 11496c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 3216c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/14 Auction House
+ Assets:Tajer 34678c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Gruulmorg 1G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Assets:Tajer 59389c
+ Equity:Gold
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/14 Player
+ Assets:Tajer 6G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Items 35s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer:Items "Plans: Wildthorn Mail" 1 @ 125s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Bids 259c
+ Assets:Bids 45s
+ Assets:Bids 4720c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Expenses:Items 8G
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Puldoost
+ Assets:Tajer 8G
+ Expenses:Items
+
+2006/03/14 Auction House
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" 1 {1.25G}
+ Assets:Tajer:Items
+
+2006/03/15 Auction House
+ Assets:Tajer 45s
+ Assets:Tajer 259c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Assets:Tajer 4720c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 12542c ; something got lost here
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 2375c
+ Expenses:Fees:Auction -2375c
+ Assets:Gruulmorg
+
+2006/03/15 Auction House
+ Assets:Danell 4c
+ Equity:Gold
+
+2006/03/15 Transfer
+ Assets:Gruulmorg 2c
+ Assets:Danell
+
+2006/03/15 Transfer
+ Assets:Danell 4250c
+ Expenses:Fees:Auction 750c
+ Assets:Gruulmorg -50s
+
+2006/03/15 Post
+ Expenses:Fees:Mail 60c
+ Assets:Danell
+
+2006/03/15 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/15 Post
+ Assets:Wyshona 40s
+ Expenses:Fees:Mail 30c
+ Assets:Danell
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8s
+ Expenses:Fees:Auction 11s
+ Assets:Wyshona
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Beaststalker's Belt" 1 @ 65G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Vendor
+ Assets:Tajer 16744c
+ Assets:Tajer 16640c
+ Equity:Gold
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 772c
+ Expenses:Fees:Auction 544c
+ Expenses:Fees:Auction 444c
+ Expenses:Fees:Auction 432c
+ Expenses:Fees:Auction 204c
+ Assets:Tajer
+
+2006/03/15 Player
+ Assets:Tajer 12s
+ Equity:Gold
+
+2006/03/15 Vendor
+ Assets:Tajer 22s
+ Equity:Gold
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 1G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 21050c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 23000c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 150s
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/16 Post
+ Expenses:Fees:Mail 90c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 1195768c
+ Assets:Tajer:Items "Beaststalker's Belt" -1 {65G} @ 1195768c
+ Income:Brokering -545768c
+
+2006/03/16 Auction House
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {21050c}
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {2.3G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1.5G}
+ Assets:Tajer:Items
+
+2006/03/16 Player
+ Assets:Tajer 4G
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Wyshona 1341s
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Gruulmorg 4c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 4c
+ Expenses:Fees:Mail 120c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 24s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 84c
+ Expenses:Fees:Auction 84c
+ Assets:Wyshona
+
+2006/03/16 Crazy Cat Lady
+ Expenses:Items 40s
+ Expenses:Items 40s
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 60c
+ Assets:Danell 5G
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Tajer 20G
+ Assets:Gruulmorg
+
+2006/03/16 Auction House
+ Assets:Tajer:Items "Pulsating Hydra Heart" 1 @ 1G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 936c
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg 30G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Gruulmorg:Items "Ace of Warlords" 2 @ 15G
+ Assets:Gruulmorg
+
+2006/03/16 Transfer
+ Assets:Tajer:Items "Ace of Warlords" 2 {15G}
+ Assets:Gruulmorg:Items
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 2104c
+ Equity:Gold
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Assets:Danell 6c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/16 General Goods Vendor
+ Expenses:Items 50c ; wrapping paper
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 1G
+ Equity:Gold
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1.5G} @ 180584c
+ Income:Brokering -165584c
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1G} @ 180584c
+ Income:Brokering -170584c
+
+2006/03/17 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Player: raev
+ Assets:Tajer:Items "Wildheart Belt" 1 {30G}
+ Assets:Tajer:Items "Ace of Warlords" -2 {15G}
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 7482c
+ Assets:Tajer
+
+2006/03/17 Post
+ Expenses:Fees:Mail 300c
+ Assets:Wyshona
+
+2006/03/17 Player
+ Assets:Wyshona 1G
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" -1 {1.25G} @ 1G
+ Expenses:Capital Loss 25s
+
+2006/03/17 Auction House (implicit transfer)
+ Expenses:Items 279s ; Recipe: Swiftness Potion
+ Assets:Wyshona
+
+2006/03/17 Auction House (implicit transfer)
+ Assets:Danell:Items "Ace of Warlords" 1 @ 3G
+ Assets:Tajer:Items "Ace of Warlords" 1 @ 3.9G
+ Assets:Tajer:Items "Holy Bologna" 1 @ 2G
+ Assets:Tajer:Items "The Emerald Dream" 1 @ 4G
+ Assets:Tajer:Items "The Arcanist's Cookbook" 1 @ 4G
+ Assets:Tajer:Items "Harnessing Shadows" 1 @ 5G
+ Assets:Tajer:Items "Garona: Book on Treachery" 1 @ 4G
+ Assets:Tajer:Items "Preserved Holly" 5 @ 20s
+ Assets:Wyshona
+
+2006/03/17 Auction House
+ Assets:Tajer 4G
+ Assets:Tajer:Items "Pulsating Hydra Heart" -1 {1G} @ 4G
+ Income:Brokering -3G
+
+2006/03/17 Auction House
+ Assets:Danell 3171c
+ Assets:Danell:Items "Ace of Warlords" -1 {3G} @ 3171c
+ Expenses:Capital Loss 26829c
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 12537c
+ Assets:Danell
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 15G
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Auction House
+ Assets:Wyshona 362450c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {21050c} @ 181225c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {2.3G} @ 181225c
+ Income:Brokering -318400c
+
+2006/03/17 Transfer
+ Assets:Danell 499560c
+ Expenses:Gifts 1G
+ Expenses:Fees:Mail 30c
+ Assets:Wyshona
+
+2006/03/17 Post
+ Expenses:Fees:Mail 90c
+ Expenses:Fees:Auction 166c
+ Assets:Gruulmorg
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 459211c
+ Expenses:Fees:Auction 81023c
+ Assets:Danell -540234c
+
+2006/03/17 Transfer
+ Assets:Tajer 662465c
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/18 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "Ace of Warlords" -1 {3.9G} @ 15G
+ Income:Brokering -111000c
+
+2006/03/18 Auction House
+ Assets:Tajer 434472c
+ Assets:Tajer:Items "Wildheart Belt" -1 {30G} @ 434472c
+ Income:Brokering -134472c
+
+2006/03/18 Auction House
+ Assets:Tajer 1995s
+ Assets:Tajer:Items "Harnessing Shadows" -1 {5G} @ 1995s
+ Income:Brokering -1495s
+
+2006/03/19 Auction House
+ Assets:Tajer 2850s
+ Assets:Tajer:Items "Garona: Book on Treachery" -1 {4G} @ 2850s
+ Income:Brokering -2450s
+
+2006/03/19 Auction House
+ Assets:Tajer 1710s
+ Assets:Tajer:Items "The Arcanist's Cookbook" -1 {4G} @ 1710s
+ Income:Brokering -1310s
+
+2006/03/19 Auction House
+ Assets:Tajer 46550c
+ Assets:Tajer:Items "Preserved Holly" -5 {20s} @ 9310c
+ Income:Brokering -36550c
+
+2006/03/19 Auction House
+ Assets:Tajer:Items "Two of Portals" 1 @ 3G
+ Assets:Tajer:Items "Two of Portals" 1 @ 2.5G
+ Assets:Tajer
+
+2006/03/20 Auction House
+ Assets:Tajer 163443c
+ Assets:Tajer:Items "Holy Bologna" -1 {2G} @ 163443c
+ Income:Brokering -143443c
+
+2006/03/20 Auction House
+ Assets:Tajer 5G
+ Assets:Tajer:Items "Two of Portals" -1 {3G} @ 5G
+ Income:Brokering -2G
+
+2006/03/20 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "The Emerald Dream" -1 {4G} @ 15G
+ Income:Brokering -11G
+
+2006/03/20 Auction House
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 170G
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Expenses:Fees:Auction 2760c
+ Expenses:Fees:Auction 2760c
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Assets:Tajer:Items "Nightblade" 1 @ 200G
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/23 Auction House
+ Assets:Tajer 1665260c
+ Assets:Tajer:Items "Orb of Deception" -1 {170G} @ 1665260c
+ Expenses:Capital Loss 34740c
+
+2006/03/26 Auction House
+ Assets:Tajer 81980c
+ Assets:Tajer:Items "Two of Portals" -1 {2.5G} @ 81980c
+ Income:Brokering -56980c
+
+2006/03/26 Player
+ Expenses:Items 150s ; Recipe: Elixir of Minor Agility
+ Expenses:Fees:Mail 30c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/27 Player
+ Assets:Tajer 160G
+ Assets:Tajer:Items "Nightblade" -1 {200G} @ 160G
+ Expenses:Capital Loss 40G
+
+2006/03/27 Player
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/26 Player
+ Expenses:Items (9G * 6) ; Traveler's backpacks
+ Expenses:Items 10G
+ Expenses:Fees:Bank 10G
+ Expenses:Fees:Mail 630c
+ Expenses:Fees:Mail 330c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/04/01 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 155G
+ Assets:Tajer
+>>>1
+ 133.98G
+ 158.85G
+ 0
+ 14.28s
+ 21.96s
+ 28.08s
+ 75.72s
+ 1.09G
+ 1.22G
+ 1.36G
+ 1.42G
+ 2.43G
+ 2.79G
+ 2.95G
+ 3.79G
+ 4.79G
+ 5.02G
+ 0
+ 15.89G
+ 0
+ 13.20s
+ 0
+ 1.15G
+ 0
+ 32.16s
+ 0
+ 30c
+ 0
+ 3.47G
+ 0
+ 23.16s
+ 0
+ 1.00G
+ 0
+ 5.94G
+ 0
+ 1.20s
+ 0
+ 3.00G
+ 0
+ 6.00G
+ 0
+ 35.00s
+ 0
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ -1.22G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ -77.41s
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ -30.21s
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ -1.24G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ 6.75G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ -1.24G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ 6.75G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.05G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.02G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.03G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -1.25G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.26G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.08G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.00G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.49G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ 50.00s
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.10G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.10G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.42G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.31G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -2.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -66.67G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -65.83G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -64.16G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.42G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.37G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.32G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.28G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.26G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.38G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.28G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -68.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -68.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -68.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -67.67G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -68.50G
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -68.50G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -70.61G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -70.61G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -72.90G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -72.90G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -74.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -71.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -74.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -74.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ -74.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ 45.17G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -9.40G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 45.17G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 42.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 51.68G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.28G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.51G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.63G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.75G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.76G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.76G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.67G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 39.07G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 43.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 58.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 38.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 37.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 37.36G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 37.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 37.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 67.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 37.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 37.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 7.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 7.27G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.72G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.52G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -21.98G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -21.23G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -21.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -22.73G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -4.67G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -4.67G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -21.23G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -4.67G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -3.67G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 13.39G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Ace of Warlords" 2 {15.00G}
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.13G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 13.41G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 13.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Plans: Wildthorn Mail" 1 {1.25G}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.63G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 17.17G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 14.38G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -12.52G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -8.52G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -8.52G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -11.52G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -8.52G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -8.20G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -8.20G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -5.52G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -8.20G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -6.95G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -8.20G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 6.80G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 6.80G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -8.20G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.11G}
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G}
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -3.79G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 12.22G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 78.00G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 79.00G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 79.00G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.07G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 73.97G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 82.07G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 94.29G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 94.30G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.80G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.80G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 28.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 43.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 43.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 31.95G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 43.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 86.49G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Wildheart Belt" 1 {30.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 86.49G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 73.05G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 86.49G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 106.44G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 106.44G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 91.49G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 106.44G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 134.94G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 134.94G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 110.44G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 134.94G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 152.04G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 152.04G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 138.94G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 152.04G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 156.70G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 156.70G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 153.04G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 156.70G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 156.70G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 156.70G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 151.20G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 167.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 167.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 153.20G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 167.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 172.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 172.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 170.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 172.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 187.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 187.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 176.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 187.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 187.55G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 187.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 187.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 17.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 17.82G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 18.09G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 17.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 17.54G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -182.46G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -180.69G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -178.92G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -177.15G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -175.38G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -174.63G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -182.46G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -15.93G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -15.93G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -12.46G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -15.93G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -7.73G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -7.73G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -13.43G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -7.73G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -6.23G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -6.23G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -6.23G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -7.73G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 152.27G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 152.27G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 192.27G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 152.27G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 152.27G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 152.27G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 206.27G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 216.27G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 226.27G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 226.33G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 226.36G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 226.37G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 152.27G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ 152.27G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {155.00G} [2006/04/01]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+ "Ace of Warlords" 1 {3.00G} [2006/03/17]
+ "Ace of Warlords" -1 {3.00G}
+ "Ace of Warlords" 1 {3.90G} [2006/03/17]
+ "Ace of Warlords" -1 {3.90G}
+ "Ace of Warlords" 2 {15.00G} [2006/03/16]
+ "Beaststalker's Belt" 1 {65.00G} [2006/03/15]
+ "Beaststalker's Belt" -1 {65.00G}
+ -2.73G
+ "Garona: Book on Treachery" 1 {4.00G} [2006/03/17]
+ "Garona: Book on Treachery" -1 {4.00G}
+ "Harnessing Shadows" 1 {5.00G} [2006/03/17]
+ "Harnessing Shadows" -1 {5.00G}
+ "Holy Bologna" 1 {2.00G} [2006/03/17]
+ "Holy Bologna" -1 {2.00G}
+ Nightblade 1 {200.00G} [2006/03/22]
+ Nightblade -1 {200.00G}
+ "Orb of Deception" 1 {155.00G} [2006/04/01]
+ "Orb of Deception" 1 {170.00G} [2006/03/21]
+ "Orb of Deception" -1 {170.00G}
+ "Plans: Mithril Shield Spike" 1 {2.11G} [2006/03/15]
+ "Plans: Mithril Shield Spike" 1 {2.30G} [2006/03/15]
+ "Plans: Wildthorn Mail" 1 {1.25G} [2006/03/14]
+ "Preserved Holly" 5 {20.00s} [2006/03/17]
+ "Preserved Holly" -5 {20.00s}
+ "Pulsating Hydra Heart" 1 {1.00G} [2006/03/16]
+ "Pulsating Hydra Heart" -1 {1.00G}
+ "Recipe: Elixir of Giant Growth" 1 {1.00G} [2006/03/15]
+ "Recipe: Elixir of Giant Growth" 1 {1.50G} [2006/03/15]
+ "The Arcanist's Cookbook" 1 {4.00G} [2006/03/17]
+ "The Arcanist's Cookbook" -1 {4.00G}
+ "The Emerald Dream" 1 {4.00G} [2006/03/17]
+ "The Emerald Dream" -1 {4.00G}
+ "Two of Portals" 1 {2.50G} [2006/03/19]
+ "Two of Portals" -1 {2.50G}
+ "Two of Portals" 1 {3.00G} [2006/03/19]
+ "Two of Portals" -1 {3.00G}
+>>>2
+=== 0
diff --git a/test/baseline/opt-lots_basis.test b/test/baseline/opt-lots_basis.test
new file mode 100644
index 00000000..51235473
--- /dev/null
+++ b/test/baseline/opt-lots_basis.test
@@ -0,0 +1,890 @@
+reg --basis
+<<<
+C 1.00s = 100c
+C 1.00G = 100s
+
+D 1.00G
+
+2006/03/14 Opening Balances
+ Assets:Tajer 1339829c
+ Assets:Gruulmorg 248720c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1428c
+ Expenses:Fees:Auction 768c
+ Expenses:Fees:Auction 612c
+ Expenses:Fees:Auction 4764c
+ Expenses:Fees:Auction 3372c
+ Expenses:Fees:Auction 1296c
+ Expenses:Fees:Auction 1332c
+ Expenses:Fees:Auction 660c
+ Expenses:Fees:Auction 10044c
+ Expenses:Fees:Auction 3588c
+ Expenses:Fees:Auction 1632c
+ Expenses:Fees:Auction 8388c
+ Expenses:Fees:Auction 9984c
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 158860c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1320c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 11496c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 3216c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/14 Auction House
+ Assets:Tajer 34678c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Gruulmorg 1G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Assets:Tajer 59389c
+ Equity:Gold
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/14 Player
+ Assets:Tajer 6G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Items 35s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer:Items "Plans: Wildthorn Mail" 1 @ 125s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Bids 259c
+ Assets:Bids 45s
+ Assets:Bids 4720c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Expenses:Items 8G
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Puldoost
+ Assets:Tajer 8G
+ Expenses:Items
+
+2006/03/14 Auction House
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" 1 {1.25G}
+ Assets:Tajer:Items
+
+2006/03/15 Auction House
+ Assets:Tajer 45s
+ Assets:Tajer 259c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Assets:Tajer 4720c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 12542c ; something got lost here
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 2375c
+ Expenses:Fees:Auction -2375c
+ Assets:Gruulmorg
+
+2006/03/15 Auction House
+ Assets:Danell 4c
+ Equity:Gold
+
+2006/03/15 Transfer
+ Assets:Gruulmorg 2c
+ Assets:Danell
+
+2006/03/15 Transfer
+ Assets:Danell 4250c
+ Expenses:Fees:Auction 750c
+ Assets:Gruulmorg -50s
+
+2006/03/15 Post
+ Expenses:Fees:Mail 60c
+ Assets:Danell
+
+2006/03/15 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/15 Post
+ Assets:Wyshona 40s
+ Expenses:Fees:Mail 30c
+ Assets:Danell
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8s
+ Expenses:Fees:Auction 11s
+ Assets:Wyshona
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Beaststalker's Belt" 1 @ 65G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Vendor
+ Assets:Tajer 16744c
+ Assets:Tajer 16640c
+ Equity:Gold
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 772c
+ Expenses:Fees:Auction 544c
+ Expenses:Fees:Auction 444c
+ Expenses:Fees:Auction 432c
+ Expenses:Fees:Auction 204c
+ Assets:Tajer
+
+2006/03/15 Player
+ Assets:Tajer 12s
+ Equity:Gold
+
+2006/03/15 Vendor
+ Assets:Tajer 22s
+ Equity:Gold
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 1G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 21050c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 23000c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 150s
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/16 Post
+ Expenses:Fees:Mail 90c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 1195768c
+ Assets:Tajer:Items "Beaststalker's Belt" -1 {65G} @ 1195768c
+ Income:Brokering -545768c
+
+2006/03/16 Auction House
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {21050c}
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {2.3G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1.5G}
+ Assets:Tajer:Items
+
+2006/03/16 Player
+ Assets:Tajer 4G
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Wyshona 1341s
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Gruulmorg 4c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 4c
+ Expenses:Fees:Mail 120c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 24s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 84c
+ Expenses:Fees:Auction 84c
+ Assets:Wyshona
+
+2006/03/16 Crazy Cat Lady
+ Expenses:Items 40s
+ Expenses:Items 40s
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 60c
+ Assets:Danell 5G
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Tajer 20G
+ Assets:Gruulmorg
+
+2006/03/16 Auction House
+ Assets:Tajer:Items "Pulsating Hydra Heart" 1 @ 1G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 936c
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg 30G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Gruulmorg:Items "Ace of Warlords" 2 @ 15G
+ Assets:Gruulmorg
+
+2006/03/16 Transfer
+ Assets:Tajer:Items "Ace of Warlords" 2 {15G}
+ Assets:Gruulmorg:Items
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 2104c
+ Equity:Gold
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Assets:Danell 6c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/16 General Goods Vendor
+ Expenses:Items 50c ; wrapping paper
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 1G
+ Equity:Gold
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1.5G} @ 180584c
+ Income:Brokering -165584c
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1G} @ 180584c
+ Income:Brokering -170584c
+
+2006/03/17 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Player: raev
+ Assets:Tajer:Items "Wildheart Belt" 1 {30G}
+ Assets:Tajer:Items "Ace of Warlords" -2 {15G}
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 7482c
+ Assets:Tajer
+
+2006/03/17 Post
+ Expenses:Fees:Mail 300c
+ Assets:Wyshona
+
+2006/03/17 Player
+ Assets:Wyshona 1G
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" -1 {1.25G} @ 1G
+ Expenses:Capital Loss 25s
+
+2006/03/17 Auction House (implicit transfer)
+ Expenses:Items 279s ; Recipe: Swiftness Potion
+ Assets:Wyshona
+
+2006/03/17 Auction House (implicit transfer)
+ Assets:Danell:Items "Ace of Warlords" 1 @ 3G
+ Assets:Tajer:Items "Ace of Warlords" 1 @ 3.9G
+ Assets:Tajer:Items "Holy Bologna" 1 @ 2G
+ Assets:Tajer:Items "The Emerald Dream" 1 @ 4G
+ Assets:Tajer:Items "The Arcanist's Cookbook" 1 @ 4G
+ Assets:Tajer:Items "Harnessing Shadows" 1 @ 5G
+ Assets:Tajer:Items "Garona: Book on Treachery" 1 @ 4G
+ Assets:Tajer:Items "Preserved Holly" 5 @ 20s
+ Assets:Wyshona
+
+2006/03/17 Auction House
+ Assets:Tajer 4G
+ Assets:Tajer:Items "Pulsating Hydra Heart" -1 {1G} @ 4G
+ Income:Brokering -3G
+
+2006/03/17 Auction House
+ Assets:Danell 3171c
+ Assets:Danell:Items "Ace of Warlords" -1 {3G} @ 3171c
+ Expenses:Capital Loss 26829c
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 12537c
+ Assets:Danell
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 15G
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Auction House
+ Assets:Wyshona 362450c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {21050c} @ 181225c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {2.3G} @ 181225c
+ Income:Brokering -318400c
+
+2006/03/17 Transfer
+ Assets:Danell 499560c
+ Expenses:Gifts 1G
+ Expenses:Fees:Mail 30c
+ Assets:Wyshona
+
+2006/03/17 Post
+ Expenses:Fees:Mail 90c
+ Expenses:Fees:Auction 166c
+ Assets:Gruulmorg
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 459211c
+ Expenses:Fees:Auction 81023c
+ Assets:Danell -540234c
+
+2006/03/17 Transfer
+ Assets:Tajer 662465c
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/18 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "Ace of Warlords" -1 {3.9G} @ 15G
+ Income:Brokering -111000c
+
+2006/03/18 Auction House
+ Assets:Tajer 434472c
+ Assets:Tajer:Items "Wildheart Belt" -1 {30G} @ 434472c
+ Income:Brokering -134472c
+
+2006/03/18 Auction House
+ Assets:Tajer 1995s
+ Assets:Tajer:Items "Harnessing Shadows" -1 {5G} @ 1995s
+ Income:Brokering -1495s
+
+2006/03/19 Auction House
+ Assets:Tajer 2850s
+ Assets:Tajer:Items "Garona: Book on Treachery" -1 {4G} @ 2850s
+ Income:Brokering -2450s
+
+2006/03/19 Auction House
+ Assets:Tajer 1710s
+ Assets:Tajer:Items "The Arcanist's Cookbook" -1 {4G} @ 1710s
+ Income:Brokering -1310s
+
+2006/03/19 Auction House
+ Assets:Tajer 46550c
+ Assets:Tajer:Items "Preserved Holly" -5 {20s} @ 9310c
+ Income:Brokering -36550c
+
+2006/03/19 Auction House
+ Assets:Tajer:Items "Two of Portals" 1 @ 3G
+ Assets:Tajer:Items "Two of Portals" 1 @ 2.5G
+ Assets:Tajer
+
+2006/03/20 Auction House
+ Assets:Tajer 163443c
+ Assets:Tajer:Items "Holy Bologna" -1 {2G} @ 163443c
+ Income:Brokering -143443c
+
+2006/03/20 Auction House
+ Assets:Tajer 5G
+ Assets:Tajer:Items "Two of Portals" -1 {3G} @ 5G
+ Income:Brokering -2G
+
+2006/03/20 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "The Emerald Dream" -1 {4G} @ 15G
+ Income:Brokering -11G
+
+2006/03/20 Auction House
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 170G
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Expenses:Fees:Auction 2760c
+ Expenses:Fees:Auction 2760c
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Assets:Tajer:Items "Nightblade" 1 @ 200G
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/23 Auction House
+ Assets:Tajer 1665260c
+ Assets:Tajer:Items "Orb of Deception" -1 {170G} @ 1665260c
+ Expenses:Capital Loss 34740c
+
+2006/03/26 Auction House
+ Assets:Tajer 81980c
+ Assets:Tajer:Items "Two of Portals" -1 {2.5G} @ 81980c
+ Income:Brokering -56980c
+
+2006/03/26 Player
+ Expenses:Items 150s ; Recipe: Elixir of Minor Agility
+ Expenses:Fees:Mail 30c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/27 Player
+ Assets:Tajer 160G
+ Assets:Tajer:Items "Nightblade" -1 {200G} @ 160G
+ Expenses:Capital Loss 40G
+
+2006/03/27 Player
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/26 Player
+ Expenses:Items (9G * 6) ; Traveler's backpacks
+ Expenses:Items 10G
+ Expenses:Fees:Bank 10G
+ Expenses:Fees:Mail 630c
+ Expenses:Fees:Mail 330c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/04/01 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 155G
+ Assets:Tajer
+>>>1
+06-Mar-14 Opening Balances Assets:Tajer 133.98G 133.98G
+ Assets:Gruulmorg 24.87G 158.85G
+ Equity:Gold -158.85G 0
+06-Mar-14 Auction House Expenses:Fees:Auction 14.28s 14.28s
+ Expenses:Fees:Auction 7.68s 21.96s
+ Expenses:Fees:Auction 6.12s 28.08s
+ Expenses:Fees:Auction 47.64s 75.72s
+ Expenses:Fees:Auction 33.72s 1.09G
+ Expenses:Fees:Auction 12.96s 1.22G
+ Expenses:Fees:Auction 13.32s 1.36G
+ Expenses:Fees:Auction 6.60s 1.42G
+ Expenses:Fees:Auction 1.00G 2.43G
+ Expenses:Fees:Auction 35.88s 2.79G
+ Expenses:Fees:Auction 16.32s 2.95G
+ Expenses:Fees:Auction 83.88s 3.79G
+ Expenses:Fees:Auction 99.84s 4.79G
+ Expenses:Fees:Auction 23.16s 5.02G
+ Assets:Tajer -5.02G 0
+06-Mar-14 Auction House Assets:Tajer 15.89G 15.89G
+ Equity:Gold -15.89G 0
+06-Mar-14 Auction House Expenses:Fees:Auction 13.20s 13.20s
+ Assets:Tajer -13.20s 0
+06-Mar-14 Auction House Assets:Tajer 1.15G 1.15G
+ Equity:Gold -1.15G 0
+06-Mar-14 Auction House Expenses:Fees:Auction 32.16s 32.16s
+ Assets:Tajer -32.16s 0
+06-Mar-14 Post Expenses:Fees:Mail 30c 30c
+ Assets:Gruulmorg -30c 0
+06-Mar-14 Auction House Assets:Tajer 3.47G 3.47G
+ Equity:Gold -3.47G 0
+06-Mar-14 Auction House Expenses:Fees:Auction 23.16s 23.16s
+ Assets:Tajer -23.16s 0
+06-Mar-14 Auction House Assets:Gruulmorg 1.00G 1.00G
+ Equity:Gold -1.00G 0
+06-Mar-14 Auction House Assets:Tajer 5.94G 5.94G
+ Equity:Gold -5.94G 0
+06-Mar-14 Post Expenses:Fees:Mail 1.20s 1.20s
+ Assets:Tajer -1.20s 0
+06-Mar-14 Player Assets:Tajer 3.00G 3.00G
+ Equity:Gold -3.00G 0
+06-Mar-14 Player Assets:Tajer 6.00G 6.00G
+ Equity:Gold -6.00G 0
+06-Mar-14 Auction House Expenses:Items 35.00s 35.00s
+ Assets:Tajer -35.00s 0
+06-Mar-14 Auction House Assets:Tajer:Items 1.25G 1.25G
+ Assets:Tajer -1.25G 0
+06-Mar-14 Auction House Assets:Bids 2.59s 2.59s
+ Assets:Bids 45.00s 47.59s
+ Assets:Bids 47.20s 94.79s
+ Assets:Tajer -94.79s 0
+06-Mar-14 Post Expenses:Fees:Mail 1.20s 1.20s
+ Assets:Tajer -1.20s 0
+06-Mar-14 Auction House Expenses:Items 8.00G 8.00G
+ Assets:Tajer -8.00G 0
+06-Mar-14 Post Expenses:Fees:Mail 1.20s 1.20s
+ Assets:Tajer -1.20s 0
+06-Mar-14 Puldoost Assets:Tajer 8.00G 8.00G
+ Expenses:Items -8.00G 0
+06-Mar-14 Auction House Assets:Wyshona:Items 1.25G 1.25G
+ Assets:Tajer:Items -1.25G 0
+06-Mar-15 Auction House Assets:Tajer 45.00s 45.00s
+ Assets:Tajer 2.59s 47.59s
+ Assets:Bids -47.59s 0
+06-Mar-15 Auction House Assets:Tajer 47.20s 47.20s
+ Assets:Bids -47.20s 0
+06-Mar-15 Auction House Expenses:Fees:Auction 1.25G 1.25G
+ Assets:Tajer -1.25G 0
+06-Mar-15 Auction House Expenses:Fees:Auction 23.75s 23.75s
+ Expenses:Fees:Auction -23.75s 0
+06-Mar-15 Auction House Assets:Danell 4c 4c
+ Equity:Gold -4c 0
+06-Mar-15 Transfer Assets:Gruulmorg 2c 2c
+ Assets:Danell -2c 0
+06-Mar-15 Transfer Assets:Danell 42.50s 42.50s
+ Expenses:Fees:Auction 7.50s 50.00s
+ Assets:Gruulmorg -50.00s 0
+06-Mar-15 Post Expenses:Fees:Mail 60c 60c
+ Assets:Danell -60c 0
+06-Mar-15 Player Assets:Tajer 3.00G 3.00G
+ Equity:Gold -3.00G 0
+06-Mar-15 Post Assets:Wyshona 40.00s 40.00s
+ Expenses:Fees:Mail 30c 40.30s
+ Assets:Danell -40.30s 0
+06-Mar-15 Auction House Expenses:Fees:Auction 8.00s 8.00s
+ Expenses:Fees:Auction 11.00s 19.00s
+ Assets:Wyshona -19.00s 0
+06-Mar-15 Auction House Assets:Tajer:Items 65.00G 65.00G
+ Assets:Tajer -65.00G 0
+06-Mar-15 Post Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Mar-15 Auction House Expenses:Fees:Auction 82.68s 82.68s
+ Assets:Tajer -82.68s 0
+06-Mar-15 Post Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Mar-15 Vendor Assets:Tajer 1.67G 1.67G
+ Assets:Tajer 1.66G 3.34G
+ Equity:Gold -3.34G 0
+06-Mar-15 Post Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Mar-15 Auction House Expenses:Fees:Auction 7.72s 7.72s
+ Expenses:Fees:Auction 5.44s 13.16s
+ Expenses:Fees:Auction 4.44s 17.60s
+ Expenses:Fees:Auction 4.32s 21.92s
+ Expenses:Fees:Auction 2.04s 23.96s
+ Assets:Tajer -23.96s 0
+06-Mar-15 Player Assets:Tajer 12.00s 12.00s
+ Equity:Gold -12.00s 0
+06-Mar-15 Vendor Assets:Tajer 22.00s 22.00s
+ Equity:Gold -22.00s 0
+06-Mar-15 Auction House Assets:Tajer:Items 1.00G 1.00G
+ Assets:Tajer -1.00G 0
+06-Mar-15 Post Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Mar-15 Auction House Expenses:Fees:Auction 82.68s 82.68s
+ Assets:Tajer -82.68s 0
+06-Mar-15 Auction House Assets:Tajer:Items 2.11G 2.11G
+ Assets:Tajer -2.11G 0
+06-Mar-15 Auction House Assets:Tajer:Items 2.30G 2.30G
+ Assets:Tajer -2.30G 0
+06-Mar-15 Auction House Assets:Tajer:Items 1.50G 1.50G
+ Assets:Tajer -1.50G 0
+06-Mar-16 Player Assets:Tajer 3.00G 3.00G
+ Equity:Gold -3.00G 0
+06-Mar-16 Post Expenses:Fees:Mail 90c 90c
+ Assets:Tajer -90c 0
+06-Mar-16 Auction House Assets:Tajer 119.58G 119.58G
+ Assets:Tajer:Items -119.58G 0
+ Income:Brokering -54.58G -54.58G
+ Equity:Capital Gains 54.58G 0
+06-Mar-16 Auction House Assets:Wyshona:Items 2.11G 2.11G
+ Assets:Wyshona:Items 2.30G 4.40G
+ Assets:Wyshona:Items 1.00G 5.40G
+ Assets:Wyshona:Items 1.50G 6.90G
+ Assets:Tajer:Items -6.90G 0
+06-Mar-16 Player Assets:Tajer 4.00G 4.00G
+ Equity:Gold -4.00G 0
+06-Mar-16 Auction House Assets:Wyshona 13.41G 13.41G
+ Equity:Gold -13.41G 0
+06-Mar-16 Auction House Assets:Gruulmorg 4c 4c
+ Assets:Danell -4c 0
+06-Mar-16 Auction House Expenses:Fees:Auction 4c 4c
+ Expenses:Fees:Mail 1.20s 1.24s
+ Assets:Danell -1.24s 0
+06-Mar-16 Auction House Expenses:Fees:Auction 24.00s 24.00s
+ Expenses:Fees:Auction 12.00s 36.00s
+ Expenses:Fees:Auction 12.00s 48.00s
+ Expenses:Fees:Auction 84c 48.84s
+ Expenses:Fees:Auction 84c 49.68s
+ Assets:Wyshona -49.68s 0
+06-Mar-16 Crazy Cat Lady Expenses:Items 40.00s 40.00s
+ Expenses:Items 40.00s 80.00s
+ Assets:Wyshona -80.00s 0
+06-Mar-16 Transfer Expenses:Fees:Mail 60c 60c
+ Assets:Danell 5.00G 5.01G
+ Assets:Wyshona -5.01G 0
+06-Mar-16 Transfer Expenses:Fees:Mail 30c 30c
+ Assets:Tajer 20.00G 20.00G
+ Assets:Gruulmorg -20.00G 0
+06-Mar-16 Auction House Assets:Tajer:Items 1.00G 1.00G
+ Assets:Tajer -1.00G 0
+06-Mar-16 Auction House Expenses:Fees:Auction 9.36s 9.36s
+ Assets:Tajer -9.36s 0
+06-Mar-16 Transfer Expenses:Fees:Mail 30c 30c
+ Assets:Gruulmorg 30.00G 30.00G
+ Assets:Tajer -30.00G 0
+06-Mar-16 Auction House Assets:Gruulmorg:Items 30.00G 30.00G
+ Assets:Gruulmorg -30.00G 0
+06-Mar-16 Transfer Assets:Tajer:Items 30.00G 30.00G
+ Assets:Gruulmorg:Items -30.00G 0
+06-Mar-16 Post Expenses:Fees:Mail 60c 60c
+ Assets:Gruulmorg -60c 0
+06-Mar-16 Post Expenses:Fees:Mail 1.20s 1.20s
+ Assets:Tajer -1.20s 0
+06-Mar-16 Auction House Assets:Tajer 21.04s 21.04s
+ Equity:Gold -21.04s 0
+06-Mar-16 Auction House Expenses:Fees:Auction 75.00s 75.00s
+ Expenses:Fees:Auction 75.00s 1.50G
+ Assets:Tajer -1.50G 0
+06-Mar-16 Transfer Assets:Danell 6c 6c
+ Assets:Gruulmorg -6c 0
+06-Mar-16 Post Expenses:Fees:Mail 60c 60c
+ Assets:Gruulmorg -60c 0
+06-Mar-16 Post Expenses:Fees:Mail 60c 60c
+ Assets:Tajer -60c 0
+06-Mar-16 General Goods Vendor Expenses:Items 50c 50c
+ Assets:Tajer -50c 0
+06-Mar-16 Player Assets:Tajer 1.00G 1.00G
+ Equity:Gold -1.00G 0
+06-Mar-17 Auction House Assets:Wyshona 18.06G 18.06G
+ Assets:Wyshona:Items -18.06G 0
+ Income:Brokering -16.56G -16.56G
+ Equity:Capital Gains 16.56G 0
+06-Mar-17 Auction House Assets:Wyshona 18.06G 18.06G
+ Assets:Wyshona:Items -18.06G 0
+ Income:Brokering -17.06G -17.06G
+ Equity:Capital Gains 17.06G 0
+06-Mar-17 Post Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Mar-17 Player: raev Assets:Tajer:Items 30.00G 30.00G
+ Assets:Tajer:Items -30.00G 0
+06-Mar-17 Auction House Expenses:Fees:Auction 74.82s 74.82s
+ Assets:Tajer -74.82s 0
+06-Mar-17 Post Expenses:Fees:Mail 3.00s 3.00s
+ Assets:Wyshona -3.00s 0
+06-Mar-17 Player Assets:Wyshona 1.00G 1.00G
+ Assets:Wyshona:Items -1.00G 0
+ Expenses:Capital Loss 25.00s 25.00s
+ Equity:Capital Losses -25.00s 0
+06-Mar-17 Auction House (impl.. Expenses:Items 2.79G 2.79G
+ Assets:Wyshona -2.79G 0
+06-Mar-17 Auction House (impl.. Assets:Danell:Items 3.00G 3.00G
+ Assets:Tajer:Items 3.90G 6.90G
+ Assets:Tajer:Items 2.00G 8.90G
+ Assets:Tajer:Items 4.00G 12.90G
+ Assets:Tajer:Items 4.00G 16.90G
+ Assets:Tajer:Items 5.00G 21.90G
+ Assets:Tajer:Items 4.00G 25.90G
+ Assets:Tajer:Items 1.00G 26.90G
+ Assets:Wyshona -26.90G 0
+06-Mar-17 Auction House Assets:Tajer 4.00G 4.00G
+ Assets:Tajer:Items -4.00G 0
+ Income:Brokering -3.00G -3.00G
+ Equity:Capital Gains 3.00G 0
+06-Mar-17 Auction House Assets:Danell 31.71s 31.71s
+ Assets:Danell:Items -31.71s 0
+ Expenses:Capital Loss 2.68G 2.68G
+ Equity:Capital Losses -2.68G 0
+06-Mar-17 Auction House Expenses:Fees:Auction 1.25G 1.25G
+ Assets:Danell -1.25G 0
+06-Mar-17 Transfer Assets:Gruulmorg 15.00G 15.00G
+ Expenses:Fees:Mail 30c 15.00G
+ Assets:Tajer -15.00G 0
+06-Mar-17 Auction House Assets:Wyshona 36.25G 36.25G
+ Assets:Wyshona:Items -18.12G 18.12G
+ Assets:Wyshona:Items -18.12G 0
+ Income:Brokering -31.84G -31.84G
+ Equity:Capital Gains 16.02G -15.82G
+ Equity:Capital Gains 15.82G 0
+06-Mar-17 Transfer Assets:Danell 49.96G 49.96G
+ Expenses:Gifts 1.00G 50.96G
+ Expenses:Fees:Mail 30c 50.96G
+ Assets:Wyshona -50.96G 0
+06-Mar-17 Post Expenses:Fees:Mail 90c 90c
+ Expenses:Fees:Auction 1.66s 2.56s
+ Assets:Gruulmorg -2.56s 0
+06-Mar-17 Transfer Assets:Gruulmorg 45.92G 45.92G
+ Expenses:Fees:Auction 8.10G 54.02G
+ Assets:Danell -54.02G 0
+06-Mar-17 Transfer Assets:Tajer 66.25G 66.25G
+ Expenses:Fees:Mail 30c 66.25G
+ Assets:Gruulmorg -66.25G 0
+06-Mar-17 Auction House Expenses:Fees:Auction 75.00s 75.00s
+ Expenses:Fees:Mail 30c 75.30s
+ Assets:Tajer -75.30s 0
+06-Mar-18 Auction House Assets:Tajer 15.00G 15.00G
+ Assets:Tajer:Items -15.00G 0
+ Income:Brokering -11.10G -11.10G
+ Equity:Capital Gains 11.10G 0
+06-Mar-18 Auction House Assets:Tajer 43.45G 43.45G
+ Assets:Tajer:Items -43.45G 0
+ Income:Brokering -13.45G -13.45G
+ Equity:Capital Gains 13.45G 0
+06-Mar-18 Auction House Assets:Tajer 19.95G 19.95G
+ Assets:Tajer:Items -19.95G 0
+ Income:Brokering -14.95G -14.95G
+ Equity:Capital Gains 14.95G 0
+06-Mar-19 Auction House Assets:Tajer 28.50G 28.50G
+ Assets:Tajer:Items -28.50G 0
+ Income:Brokering -24.50G -24.50G
+ Equity:Capital Gains 24.50G 0
+06-Mar-19 Auction House Assets:Tajer 17.10G 17.10G
+ Assets:Tajer:Items -17.10G 0
+ Income:Brokering -13.10G -13.10G
+ Equity:Capital Gains 13.10G 0
+06-Mar-19 Auction House Assets:Tajer 4.65G 4.65G
+ Assets:Tajer:Items -4.65G 0
+ Income:Brokering -3.65G -3.65G
+ Equity:Capital Gains 3.65G 0
+06-Mar-19 Auction House Assets:Tajer:Items 3.00G 3.00G
+ Assets:Tajer:Items 2.50G 5.50G
+ Assets:Tajer -5.50G 0
+06-Mar-20 Auction House Assets:Tajer 16.34G 16.34G
+ Assets:Tajer:Items -16.34G 0
+ Income:Brokering -14.34G -14.34G
+ Equity:Capital Gains 14.34G 0
+06-Mar-20 Auction House Assets:Tajer 5.00G 5.00G
+ Assets:Tajer:Items -5.00G 0
+ Income:Brokering -2.00G -2.00G
+ Equity:Capital Gains 2.00G 0
+06-Mar-20 Auction House Assets:Tajer 15.00G 15.00G
+ Assets:Tajer:Items -15.00G 0
+ Income:Brokering -11.00G -11.00G
+ Equity:Capital Gains 11.00G 0
+06-Mar-20 Auction House Expenses:Fees:Mail 60c 60c
+ Assets:Tajer -60c 0
+06-Mar-21 Auction House Assets:Tajer:Items 170.00G 170.00G
+ Assets:Tajer -170.00G 0
+06-Mar-21 Auction House Expenses:Fees:Auction 27.60s 27.60s
+ Expenses:Fees:Auction 27.60s 55.20s
+ Assets:Tajer -55.20s 0
+06-Mar-22 Auction House Assets:Tajer:Items 200.00G 200.00G
+ Assets:Tajer -200.00G 0
+06-Mar-22 Auction House Expenses:Fees:Auction 1.77G 1.77G
+ Expenses:Fees:Auction 1.77G 3.54G
+ Expenses:Fees:Auction 1.77G 5.31G
+ Expenses:Fees:Auction 1.77G 7.08G
+ Expenses:Fees:Auction 75.00s 7.83G
+ Assets:Tajer -7.83G 0
+06-Mar-23 Auction House Assets:Tajer 166.53G 166.53G
+ Assets:Tajer:Items -166.53G 0
+ Expenses:Capital Loss 3.47G 3.47G
+ Equity:Capital Losses -3.47G 0
+06-Mar-26 Auction House Assets:Tajer 8.20G 8.20G
+ Assets:Tajer:Items -8.20G 0
+ Income:Brokering -5.70G -5.70G
+ Equity:Capital Gains 5.70G 0
+06-Mar-26 Player Expenses:Items 1.50G 1.50G
+ Expenses:Fees:Mail 30c 1.50G
+ Expenses:Fees:Mail 30c 1.51G
+ Assets:Tajer -1.51G 0
+06-Mar-26 Player Expenses:Items 54.00G 54.00G
+ Expenses:Items 10.00G 64.00G
+ Expenses:Fees:Bank 10.00G 74.00G
+ Expenses:Fees:Mail 6.30s 74.06G
+ Expenses:Fees:Mail 3.30s 74.10G
+ Expenses:Fees:Mail 30c 74.10G
+ Assets:Tajer -74.10G 0
+06-Mar-27 Player Assets:Tajer 160.00G 160.00G
+ Assets:Tajer:Items -160.00G 0
+ Expenses:Capital Loss 40.00G 40.00G
+ Equity:Capital Losses -40.00G 0
+06-Mar-27 Player Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Apr-01 Auction House Assets:Tajer:Items 155.00G 155.00G
+ Assets:Tajer -155.00G 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-lots_basis_base.test b/test/baseline/opt-lots_basis_base.test
new file mode 100644
index 00000000..2fa1fdb1
--- /dev/null
+++ b/test/baseline/opt-lots_basis_base.test
@@ -0,0 +1,891 @@
+reg --basis --base
+<<<
+C 1.00s = 100c
+C 1.00G = 100s
+
+D 1.00G
+
+2006/03/14 Opening Balances
+ Assets:Tajer 1339829c
+ Assets:Gruulmorg 248720c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1428c
+ Expenses:Fees:Auction 768c
+ Expenses:Fees:Auction 612c
+ Expenses:Fees:Auction 4764c
+ Expenses:Fees:Auction 3372c
+ Expenses:Fees:Auction 1296c
+ Expenses:Fees:Auction 1332c
+ Expenses:Fees:Auction 660c
+ Expenses:Fees:Auction 10044c
+ Expenses:Fees:Auction 3588c
+ Expenses:Fees:Auction 1632c
+ Expenses:Fees:Auction 8388c
+ Expenses:Fees:Auction 9984c
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 158860c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1320c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 11496c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 3216c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/14 Auction House
+ Assets:Tajer 34678c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Gruulmorg 1G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Assets:Tajer 59389c
+ Equity:Gold
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/14 Player
+ Assets:Tajer 6G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Items 35s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer:Items "Plans: Wildthorn Mail" 1 @ 125s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Bids 259c
+ Assets:Bids 45s
+ Assets:Bids 4720c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Expenses:Items 8G
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Puldoost
+ Assets:Tajer 8G
+ Expenses:Items
+
+2006/03/14 Auction House
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" 1 {1.25G}
+ Assets:Tajer:Items
+
+2006/03/15 Auction House
+ Assets:Tajer 45s
+ Assets:Tajer 259c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Assets:Tajer 4720c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 12542c ; something got lost here
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 2375c
+ Expenses:Fees:Auction -2375c
+ Assets:Gruulmorg
+
+2006/03/15 Auction House
+ Assets:Danell 4c
+ Equity:Gold
+
+2006/03/15 Transfer
+ Assets:Gruulmorg 2c
+ Assets:Danell
+
+2006/03/15 Transfer
+ Assets:Danell 4250c
+ Expenses:Fees:Auction 750c
+ Assets:Gruulmorg -50s
+
+2006/03/15 Post
+ Expenses:Fees:Mail 60c
+ Assets:Danell
+
+2006/03/15 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/15 Post
+ Assets:Wyshona 40s
+ Expenses:Fees:Mail 30c
+ Assets:Danell
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8s
+ Expenses:Fees:Auction 11s
+ Assets:Wyshona
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Beaststalker's Belt" 1 @ 65G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Vendor
+ Assets:Tajer 16744c
+ Assets:Tajer 16640c
+ Equity:Gold
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 772c
+ Expenses:Fees:Auction 544c
+ Expenses:Fees:Auction 444c
+ Expenses:Fees:Auction 432c
+ Expenses:Fees:Auction 204c
+ Assets:Tajer
+
+2006/03/15 Player
+ Assets:Tajer 12s
+ Equity:Gold
+
+2006/03/15 Vendor
+ Assets:Tajer 22s
+ Equity:Gold
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 1G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 21050c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 23000c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 150s
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/16 Post
+ Expenses:Fees:Mail 90c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 1195768c
+ Assets:Tajer:Items "Beaststalker's Belt" -1 {65G} @ 1195768c
+ Income:Brokering -545768c
+
+2006/03/16 Auction House
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {21050c}
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {2.3G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1.5G}
+ Assets:Tajer:Items
+
+2006/03/16 Player
+ Assets:Tajer 4G
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Wyshona 1341s
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Gruulmorg 4c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 4c
+ Expenses:Fees:Mail 120c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 24s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 84c
+ Expenses:Fees:Auction 84c
+ Assets:Wyshona
+
+2006/03/16 Crazy Cat Lady
+ Expenses:Items 40s
+ Expenses:Items 40s
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 60c
+ Assets:Danell 5G
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Tajer 20G
+ Assets:Gruulmorg
+
+2006/03/16 Auction House
+ Assets:Tajer:Items "Pulsating Hydra Heart" 1 @ 1G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 936c
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg 30G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Gruulmorg:Items "Ace of Warlords" 2 @ 15G
+ Assets:Gruulmorg
+
+2006/03/16 Transfer
+ Assets:Tajer:Items "Ace of Warlords" 2 {15G}
+ Assets:Gruulmorg:Items
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 2104c
+ Equity:Gold
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Assets:Danell 6c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/16 General Goods Vendor
+ Expenses:Items 50c ; wrapping paper
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 1G
+ Equity:Gold
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1.5G} @ 180584c
+ Income:Brokering -165584c
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1G} @ 180584c
+ Income:Brokering -170584c
+
+2006/03/17 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Player: raev
+ Assets:Tajer:Items "Wildheart Belt" 1 {30G}
+ Assets:Tajer:Items "Ace of Warlords" -2 {15G}
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 7482c
+ Assets:Tajer
+
+2006/03/17 Post
+ Expenses:Fees:Mail 300c
+ Assets:Wyshona
+
+2006/03/17 Player
+ Assets:Wyshona 1G
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" -1 {1.25G} @ 1G
+ Expenses:Capital Loss 25s
+
+2006/03/17 Auction House (implicit transfer)
+ Expenses:Items 279s ; Recipe: Swiftness Potion
+ Assets:Wyshona
+
+2006/03/17 Auction House (implicit transfer)
+ Assets:Danell:Items "Ace of Warlords" 1 @ 3G
+ Assets:Tajer:Items "Ace of Warlords" 1 @ 3.9G
+ Assets:Tajer:Items "Holy Bologna" 1 @ 2G
+ Assets:Tajer:Items "The Emerald Dream" 1 @ 4G
+ Assets:Tajer:Items "The Arcanist's Cookbook" 1 @ 4G
+ Assets:Tajer:Items "Harnessing Shadows" 1 @ 5G
+ Assets:Tajer:Items "Garona: Book on Treachery" 1 @ 4G
+ Assets:Tajer:Items "Preserved Holly" 5 @ 20s
+ Assets:Wyshona
+
+2006/03/17 Auction House
+ Assets:Tajer 4G
+ Assets:Tajer:Items "Pulsating Hydra Heart" -1 {1G} @ 4G
+ Income:Brokering -3G
+
+2006/03/17 Auction House
+ Assets:Danell 3171c
+ Assets:Danell:Items "Ace of Warlords" -1 {3G} @ 3171c
+ Expenses:Capital Loss 26829c
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 12537c
+ Assets:Danell
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 15G
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Auction House
+ Assets:Wyshona 362450c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {21050c} @ 181225c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {2.3G} @ 181225c
+ Income:Brokering -318400c
+
+2006/03/17 Transfer
+ Assets:Danell 499560c
+ Expenses:Gifts 1G
+ Expenses:Fees:Mail 30c
+ Assets:Wyshona
+
+2006/03/17 Post
+ Expenses:Fees:Mail 90c
+ Expenses:Fees:Auction 166c
+ Assets:Gruulmorg
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 459211c
+ Expenses:Fees:Auction 81023c
+ Assets:Danell -540234c
+
+2006/03/17 Transfer
+ Assets:Tajer 662465c
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/18 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "Ace of Warlords" -1 {3.9G} @ 15G
+ Income:Brokering -111000c
+
+2006/03/18 Auction House
+ Assets:Tajer 434472c
+ Assets:Tajer:Items "Wildheart Belt" -1 {30G} @ 434472c
+ Income:Brokering -134472c
+
+2006/03/18 Auction House
+ Assets:Tajer 1995s
+ Assets:Tajer:Items "Harnessing Shadows" -1 {5G} @ 1995s
+ Income:Brokering -1495s
+
+2006/03/19 Auction House
+ Assets:Tajer 2850s
+ Assets:Tajer:Items "Garona: Book on Treachery" -1 {4G} @ 2850s
+ Income:Brokering -2450s
+
+2006/03/19 Auction House
+ Assets:Tajer 1710s
+ Assets:Tajer:Items "The Arcanist's Cookbook" -1 {4G} @ 1710s
+ Income:Brokering -1310s
+
+2006/03/19 Auction House
+ Assets:Tajer 46550c
+ Assets:Tajer:Items "Preserved Holly" -5 {20s} @ 9310c
+ Income:Brokering -36550c
+
+2006/03/19 Auction House
+ Assets:Tajer:Items "Two of Portals" 1 @ 3G
+ Assets:Tajer:Items "Two of Portals" 1 @ 2.5G
+ Assets:Tajer
+
+2006/03/20 Auction House
+ Assets:Tajer 163443c
+ Assets:Tajer:Items "Holy Bologna" -1 {2G} @ 163443c
+ Income:Brokering -143443c
+
+2006/03/20 Auction House
+ Assets:Tajer 5G
+ Assets:Tajer:Items "Two of Portals" -1 {3G} @ 5G
+ Income:Brokering -2G
+
+2006/03/20 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "The Emerald Dream" -1 {4G} @ 15G
+ Income:Brokering -11G
+
+2006/03/20 Auction House
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 170G
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Expenses:Fees:Auction 2760c
+ Expenses:Fees:Auction 2760c
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Assets:Tajer:Items "Nightblade" 1 @ 200G
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/23 Auction House
+ Assets:Tajer 1665260c
+ Assets:Tajer:Items "Orb of Deception" -1 {170G} @ 1665260c
+ Expenses:Capital Loss 34740c
+
+2006/03/26 Auction House
+ Assets:Tajer 81980c
+ Assets:Tajer:Items "Two of Portals" -1 {2.5G} @ 81980c
+ Income:Brokering -56980c
+
+2006/03/26 Player
+ Expenses:Items 150s ; Recipe: Elixir of Minor Agility
+ Expenses:Fees:Mail 30c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/27 Player
+ Assets:Tajer 160G
+ Assets:Tajer:Items "Nightblade" -1 {200G} @ 160G
+ Expenses:Capital Loss 40G
+
+2006/03/27 Player
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/26 Player
+ Expenses:Items (9G * 6) ; Traveler's backpacks
+ Expenses:Items 10G
+ Expenses:Fees:Bank 10G
+ Expenses:Fees:Mail 630c
+ Expenses:Fees:Mail 330c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/04/01 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 155G
+ Assets:Tajer
+
+>>>1
+06-Mar-14 Opening Balances Assets:Tajer 1339829c 1339829c
+ Assets:Gruulmorg 248720c 1588549c
+ Equity:Gold -1588549c 0
+06-Mar-14 Auction House Expenses:Fees:Auction 1428c 1428c
+ Expenses:Fees:Auction 768c 2196c
+ Expenses:Fees:Auction 612c 2808c
+ Expenses:Fees:Auction 4764c 7572c
+ Expenses:Fees:Auction 3372c 10944c
+ Expenses:Fees:Auction 1296c 12240c
+ Expenses:Fees:Auction 1332c 13572c
+ Expenses:Fees:Auction 660c 14232c
+ Expenses:Fees:Auction 10044c 24276c
+ Expenses:Fees:Auction 3588c 27864c
+ Expenses:Fees:Auction 1632c 29496c
+ Expenses:Fees:Auction 8388c 37884c
+ Expenses:Fees:Auction 9984c 47868c
+ Expenses:Fees:Auction 2316c 50184c
+ Assets:Tajer -50184c 0
+06-Mar-14 Auction House Assets:Tajer 158860c 158860c
+ Equity:Gold -158860c 0
+06-Mar-14 Auction House Expenses:Fees:Auction 1320c 1320c
+ Assets:Tajer -1320c 0
+06-Mar-14 Auction House Assets:Tajer 11496c 11496c
+ Equity:Gold -11496c 0
+06-Mar-14 Auction House Expenses:Fees:Auction 3216c 3216c
+ Assets:Tajer -3216c 0
+06-Mar-14 Post Expenses:Fees:Mail 30c 30c
+ Assets:Gruulmorg -30c 0
+06-Mar-14 Auction House Assets:Tajer 34678c 34678c
+ Equity:Gold -34678c 0
+06-Mar-14 Auction House Expenses:Fees:Auction 2316c 2316c
+ Assets:Tajer -2316c 0
+06-Mar-14 Auction House Assets:Gruulmorg 10000c 10000c
+ Equity:Gold -10000c 0
+06-Mar-14 Auction House Assets:Tajer 59389c 59389c
+ Equity:Gold -59389c 0
+06-Mar-14 Post Expenses:Fees:Mail 120c 120c
+ Assets:Tajer -120c 0
+06-Mar-14 Player Assets:Tajer 30000c 30000c
+ Equity:Gold -30000c 0
+06-Mar-14 Player Assets:Tajer 60000c 60000c
+ Equity:Gold -60000c 0
+06-Mar-14 Auction House Expenses:Items 3500c 3500c
+ Assets:Tajer -3500c 0
+06-Mar-14 Auction House Assets:Tajer:Items 12500c 12500c
+ Assets:Tajer -12500c 0
+06-Mar-14 Auction House Assets:Bids 259c 259c
+ Assets:Bids 4500c 4759c
+ Assets:Bids 4720c 9479c
+ Assets:Tajer -9479c 0
+06-Mar-14 Post Expenses:Fees:Mail 120c 120c
+ Assets:Tajer -120c 0
+06-Mar-14 Auction House Expenses:Items 80000c 80000c
+ Assets:Tajer -80000c 0
+06-Mar-14 Post Expenses:Fees:Mail 120c 120c
+ Assets:Tajer -120c 0
+06-Mar-14 Puldoost Assets:Tajer 80000c 80000c
+ Expenses:Items -80000c 0
+06-Mar-14 Auction House Assets:Wyshona:Items 12500c 12500c
+ Assets:Tajer:Items -12500c 0
+06-Mar-15 Auction House Assets:Tajer 4500c 4500c
+ Assets:Tajer 259c 4759c
+ Assets:Bids -4759c 0
+06-Mar-15 Auction House Assets:Tajer 4720c 4720c
+ Assets:Bids -4720c 0
+06-Mar-15 Auction House Expenses:Fees:Auction 12542c 12542c
+ Assets:Tajer -12542c 0
+06-Mar-15 Auction House Expenses:Fees:Auction 2375c 2375c
+ Expenses:Fees:Auction -2375c 0
+06-Mar-15 Auction House Assets:Danell 4c 4c
+ Equity:Gold -4c 0
+06-Mar-15 Transfer Assets:Gruulmorg 2c 2c
+ Assets:Danell -2c 0
+06-Mar-15 Transfer Assets:Danell 4250c 4250c
+ Expenses:Fees:Auction 750c 5000c
+ Assets:Gruulmorg -5000c 0
+06-Mar-15 Post Expenses:Fees:Mail 60c 60c
+ Assets:Danell -60c 0
+06-Mar-15 Player Assets:Tajer 30000c 30000c
+ Equity:Gold -30000c 0
+06-Mar-15 Post Assets:Wyshona 4000c 4000c
+ Expenses:Fees:Mail 30c 4030c
+ Assets:Danell -4030c 0
+06-Mar-15 Auction House Expenses:Fees:Auction 800c 800c
+ Expenses:Fees:Auction 1100c 1900c
+ Assets:Wyshona -1900c 0
+06-Mar-15 Auction House Assets:Tajer:Items 650000c 650000c
+ Assets:Tajer -650000c 0
+06-Mar-15 Post Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Mar-15 Auction House Expenses:Fees:Auction 8268c 8268c
+ Assets:Tajer -8268c 0
+06-Mar-15 Post Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Mar-15 Vendor Assets:Tajer 16744c 16744c
+ Assets:Tajer 16640c 33384c
+ Equity:Gold -33384c 0
+06-Mar-15 Post Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Mar-15 Auction House Expenses:Fees:Auction 772c 772c
+ Expenses:Fees:Auction 544c 1316c
+ Expenses:Fees:Auction 444c 1760c
+ Expenses:Fees:Auction 432c 2192c
+ Expenses:Fees:Auction 204c 2396c
+ Assets:Tajer -2396c 0
+06-Mar-15 Player Assets:Tajer 1200c 1200c
+ Equity:Gold -1200c 0
+06-Mar-15 Vendor Assets:Tajer 2200c 2200c
+ Equity:Gold -2200c 0
+06-Mar-15 Auction House Assets:Tajer:Items 10000c 10000c
+ Assets:Tajer -10000c 0
+06-Mar-15 Post Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Mar-15 Auction House Expenses:Fees:Auction 8268c 8268c
+ Assets:Tajer -8268c 0
+06-Mar-15 Auction House Assets:Tajer:Items 21050c 21050c
+ Assets:Tajer -21050c 0
+06-Mar-15 Auction House Assets:Tajer:Items 23000c 23000c
+ Assets:Tajer -23000c 0
+06-Mar-15 Auction House Assets:Tajer:Items 15000c 15000c
+ Assets:Tajer -15000c 0
+06-Mar-16 Player Assets:Tajer 30000c 30000c
+ Equity:Gold -30000c 0
+06-Mar-16 Post Expenses:Fees:Mail 90c 90c
+ Assets:Tajer -90c 0
+06-Mar-16 Auction House Assets:Tajer 1195768c 1195768c
+ Assets:Tajer:Items -1195768c 0
+ Income:Brokering -545768c -545768c
+ Equity:Capital Gains 545768c 0
+06-Mar-16 Auction House Assets:Wyshona:Items 21050c 21050c
+ Assets:Wyshona:Items 23000c 44050c
+ Assets:Wyshona:Items 10000c 54050c
+ Assets:Wyshona:Items 15000c 69050c
+ Assets:Tajer:Items -69050c 0
+06-Mar-16 Player Assets:Tajer 40000c 40000c
+ Equity:Gold -40000c 0
+06-Mar-16 Auction House Assets:Wyshona 134100c 134100c
+ Equity:Gold -134100c 0
+06-Mar-16 Auction House Assets:Gruulmorg 4c 4c
+ Assets:Danell -4c 0
+06-Mar-16 Auction House Expenses:Fees:Auction 4c 4c
+ Expenses:Fees:Mail 120c 124c
+ Assets:Danell -124c 0
+06-Mar-16 Auction House Expenses:Fees:Auction 2400c 2400c
+ Expenses:Fees:Auction 1200c 3600c
+ Expenses:Fees:Auction 1200c 4800c
+ Expenses:Fees:Auction 84c 4884c
+ Expenses:Fees:Auction 84c 4968c
+ Assets:Wyshona -4968c 0
+06-Mar-16 Crazy Cat Lady Expenses:Items 4000c 4000c
+ Expenses:Items 4000c 8000c
+ Assets:Wyshona -8000c 0
+06-Mar-16 Transfer Expenses:Fees:Mail 60c 60c
+ Assets:Danell 50000c 50060c
+ Assets:Wyshona -50060c 0
+06-Mar-16 Transfer Expenses:Fees:Mail 30c 30c
+ Assets:Tajer 200000c 200030c
+ Assets:Gruulmorg -200030c 0
+06-Mar-16 Auction House Assets:Tajer:Items 10000c 10000c
+ Assets:Tajer -10000c 0
+06-Mar-16 Auction House Expenses:Fees:Auction 936c 936c
+ Assets:Tajer -936c 0
+06-Mar-16 Transfer Expenses:Fees:Mail 30c 30c
+ Assets:Gruulmorg 300000c 300030c
+ Assets:Tajer -300030c 0
+06-Mar-16 Auction House Assets:Gruulmorg:Items 300000c 300000c
+ Assets:Gruulmorg -300000c 0
+06-Mar-16 Transfer Assets:Tajer:Items 300000c 300000c
+ Assets:Gruulmorg:Items -300000c 0
+06-Mar-16 Post Expenses:Fees:Mail 60c 60c
+ Assets:Gruulmorg -60c 0
+06-Mar-16 Post Expenses:Fees:Mail 120c 120c
+ Assets:Tajer -120c 0
+06-Mar-16 Auction House Assets:Tajer 2104c 2104c
+ Equity:Gold -2104c 0
+06-Mar-16 Auction House Expenses:Fees:Auction 7500c 7500c
+ Expenses:Fees:Auction 7500c 15000c
+ Assets:Tajer -15000c 0
+06-Mar-16 Transfer Assets:Danell 6c 6c
+ Assets:Gruulmorg -6c 0
+06-Mar-16 Post Expenses:Fees:Mail 60c 60c
+ Assets:Gruulmorg -60c 0
+06-Mar-16 Post Expenses:Fees:Mail 60c 60c
+ Assets:Tajer -60c 0
+06-Mar-16 General Goods Vendor Expenses:Items 50c 50c
+ Assets:Tajer -50c 0
+06-Mar-16 Player Assets:Tajer 10000c 10000c
+ Equity:Gold -10000c 0
+06-Mar-17 Auction House Assets:Wyshona 180584c 180584c
+ Assets:Wyshona:Items -180584c 0
+ Income:Brokering -165584c -165584c
+ Equity:Capital Gains 165584c 0
+06-Mar-17 Auction House Assets:Wyshona 180584c 180584c
+ Assets:Wyshona:Items -180584c 0
+ Income:Brokering -170584c -170584c
+ Equity:Capital Gains 170584c 0
+06-Mar-17 Post Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Mar-17 Player: raev Assets:Tajer:Items 300000c 300000c
+ Assets:Tajer:Items -300000c 0
+06-Mar-17 Auction House Expenses:Fees:Auction 7482c 7482c
+ Assets:Tajer -7482c 0
+06-Mar-17 Post Expenses:Fees:Mail 300c 300c
+ Assets:Wyshona -300c 0
+06-Mar-17 Player Assets:Wyshona 10000c 10000c
+ Assets:Wyshona:Items -10000c 0
+ Expenses:Capital Loss 2500c 2500c
+ Equity:Capital Losses -2500c 0
+06-Mar-17 Auction House (impl.. Expenses:Items 27900c 27900c
+ Assets:Wyshona -27900c 0
+06-Mar-17 Auction House (impl.. Assets:Danell:Items 30000c 30000c
+ Assets:Tajer:Items 39000c 69000c
+ Assets:Tajer:Items 20000c 89000c
+ Assets:Tajer:Items 40000c 129000c
+ Assets:Tajer:Items 40000c 169000c
+ Assets:Tajer:Items 50000c 219000c
+ Assets:Tajer:Items 40000c 259000c
+ Assets:Tajer:Items 10000c 269000c
+ Assets:Wyshona -269000c 0
+06-Mar-17 Auction House Assets:Tajer 40000c 40000c
+ Assets:Tajer:Items -40000c 0
+ Income:Brokering -30000c -30000c
+ Equity:Capital Gains 30000c 0
+06-Mar-17 Auction House Assets:Danell 3171c 3171c
+ Assets:Danell:Items -3171c 0
+ Expenses:Capital Loss 26829c 26829c
+ Equity:Capital Losses -26829c 0
+06-Mar-17 Auction House Expenses:Fees:Auction 12537c 12537c
+ Assets:Danell -12537c 0
+06-Mar-17 Transfer Assets:Gruulmorg 150000c 150000c
+ Expenses:Fees:Mail 30c 150030c
+ Assets:Tajer -150030c 0
+06-Mar-17 Auction House Assets:Wyshona 362450c 362450c
+ Assets:Wyshona:Items -181225c 181225c
+ Assets:Wyshona:Items -181225c 0
+ Income:Brokering -318400c -318400c
+ Equity:Capital Gains 160175c -158225c
+ Equity:Capital Gains 158225c 0
+06-Mar-17 Transfer Assets:Danell 499560c 499560c
+ Expenses:Gifts 10000c 509560c
+ Expenses:Fees:Mail 30c 509590c
+ Assets:Wyshona -509590c 0
+06-Mar-17 Post Expenses:Fees:Mail 90c 90c
+ Expenses:Fees:Auction 166c 256c
+ Assets:Gruulmorg -256c 0
+06-Mar-17 Transfer Assets:Gruulmorg 459211c 459211c
+ Expenses:Fees:Auction 81023c 540234c
+ Assets:Danell -540234c 0
+06-Mar-17 Transfer Assets:Tajer 662465c 662465c
+ Expenses:Fees:Mail 30c 662495c
+ Assets:Gruulmorg -662495c 0
+06-Mar-17 Auction House Expenses:Fees:Auction 7500c 7500c
+ Expenses:Fees:Mail 30c 7530c
+ Assets:Tajer -7530c 0
+06-Mar-18 Auction House Assets:Tajer 150000c 150000c
+ Assets:Tajer:Items -150000c 0
+ Income:Brokering -111000c -111000c
+ Equity:Capital Gains 111000c 0
+06-Mar-18 Auction House Assets:Tajer 434472c 434472c
+ Assets:Tajer:Items -434472c 0
+ Income:Brokering -134472c -134472c
+ Equity:Capital Gains 134472c 0
+06-Mar-18 Auction House Assets:Tajer 199500c 199500c
+ Assets:Tajer:Items -199500c 0
+ Income:Brokering -149500c -149500c
+ Equity:Capital Gains 149500c 0
+06-Mar-19 Auction House Assets:Tajer 285000c 285000c
+ Assets:Tajer:Items -285000c 0
+ Income:Brokering -245000c -245000c
+ Equity:Capital Gains 245000c 0
+06-Mar-19 Auction House Assets:Tajer 171000c 171000c
+ Assets:Tajer:Items -171000c 0
+ Income:Brokering -131000c -131000c
+ Equity:Capital Gains 131000c 0
+06-Mar-19 Auction House Assets:Tajer 46550c 46550c
+ Assets:Tajer:Items -46550c 0
+ Income:Brokering -36550c -36550c
+ Equity:Capital Gains 36550c 0
+06-Mar-19 Auction House Assets:Tajer:Items 30000c 30000c
+ Assets:Tajer:Items 25000c 55000c
+ Assets:Tajer -55000c 0
+06-Mar-20 Auction House Assets:Tajer 163443c 163443c
+ Assets:Tajer:Items -163443c 0
+ Income:Brokering -143443c -143443c
+ Equity:Capital Gains 143443c 0
+06-Mar-20 Auction House Assets:Tajer 50000c 50000c
+ Assets:Tajer:Items -50000c 0
+ Income:Brokering -20000c -20000c
+ Equity:Capital Gains 20000c 0
+06-Mar-20 Auction House Assets:Tajer 150000c 150000c
+ Assets:Tajer:Items -150000c 0
+ Income:Brokering -110000c -110000c
+ Equity:Capital Gains 110000c 0
+06-Mar-20 Auction House Expenses:Fees:Mail 60c 60c
+ Assets:Tajer -60c 0
+06-Mar-21 Auction House Assets:Tajer:Items 1700000c 1700000c
+ Assets:Tajer -1700000c 0
+06-Mar-21 Auction House Expenses:Fees:Auction 2760c 2760c
+ Expenses:Fees:Auction 2760c 5520c
+ Assets:Tajer -5520c 0
+06-Mar-22 Auction House Assets:Tajer:Items 2000000c 2000000c
+ Assets:Tajer -2000000c 0
+06-Mar-22 Auction House Expenses:Fees:Auction 17700c 17700c
+ Expenses:Fees:Auction 17700c 35400c
+ Expenses:Fees:Auction 17700c 53100c
+ Expenses:Fees:Auction 17700c 70800c
+ Expenses:Fees:Auction 7500c 78300c
+ Assets:Tajer -78300c 0
+06-Mar-23 Auction House Assets:Tajer 1665260c 1665260c
+ Assets:Tajer:Items -1665260c 0
+ Expenses:Capital Loss 34740c 34740c
+ Equity:Capital Losses -34740c 0
+06-Mar-26 Auction House Assets:Tajer 81980c 81980c
+ Assets:Tajer:Items -81980c 0
+ Income:Brokering -56980c -56980c
+ Equity:Capital Gains 56980c 0
+06-Mar-26 Player Expenses:Items 15000c 15000c
+ Expenses:Fees:Mail 30c 15030c
+ Expenses:Fees:Mail 30c 15060c
+ Assets:Tajer -15060c 0
+06-Mar-26 Player Expenses:Items 540000c 540000c
+ Expenses:Items 100000c 640000c
+ Expenses:Fees:Bank 100000c 740000c
+ Expenses:Fees:Mail 630c 740630c
+ Expenses:Fees:Mail 330c 740960c
+ Expenses:Fees:Mail 30c 740990c
+ Assets:Tajer -740990c 0
+06-Mar-27 Player Assets:Tajer 1600000c 1600000c
+ Assets:Tajer:Items -1600000c 0
+ Expenses:Capital Loss 400000c 400000c
+ Equity:Capital Losses -400000c 0
+06-Mar-27 Player Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
+06-Apr-01 Auction House Assets:Tajer:Items 1550000c 1550000c
+ Assets:Tajer -1550000c 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-market.test b/test/baseline/opt-market.test
new file mode 100644
index 00000000..b6c0ed6d
--- /dev/null
+++ b/test/baseline/opt-market.test
@@ -0,0 +1,66 @@
+reg --market stocks
+<<<
+2009/01/01 Sample 1a
+ Assets:Brokerage:Stocks 100 S
+ Assets:Brokerage:Cash -100 P
+
+P 2009/01/01 00:00:00 S 2 P
+
+2009/02/01 Sample 2a
+ Assets:Brokerage:Stocks 100 S @ 1 P
+ Assets:Brokerage:Cash
+
+P 2009/02/01 00:00:00 S 4 P
+
+2009/03/01 Sample 3a
+ Assets:Brokerage:Stocks 100 S @@ 100 P
+ Assets:Brokerage:Cash
+
+P 2009/03/01 00:00:00 S 8 P
+
+2009/04/01 Sample 4a
+ Assets:Brokerage:Cash 100 P
+ Assets:Brokerage:Stocks -100 S {1 P}
+
+P 2009/04/01 00:00:00 S 16 P
+
+; In this usage case, the top amount is always secondary
+; 2010/01/01 Sample 1b
+; Assets:Brokerage:Cash -100 P
+; Assets:Brokerage:Stocks 100 S
+;
+; P 2010/01/01 00:00:00 S 2 P
+
+2010/02/01 Sample 2b
+ Assets:Brokerage:Cash
+ Assets:Brokerage:Stocks 100 S @ 1 P
+
+P 2010/02/01 00:00:00 S 4 P
+
+2010/03/01 Sample 3b
+ Assets:Brokerage:Cash
+ Assets:Brokerage:Stocks 100 S @@ 100 P
+
+P 2010/03/01 00:00:00 S 8 P
+
+2010/04/01 Sample 4b
+ Assets:Brokerage:Stocks -100 S {1 P}
+ Assets:Brokerage:Cash 100 P
+
+P 2010/04/01 00:00:00 S 16 P
+>>>1
+09-Jan-01 Sample 1a As:Brokerage:Stocks 200 P 200 P
+09-Feb-01 Commodities revalued <Revalued> 200 P 400 P
+09-Feb-01 Sample 2a As:Brokerage:Stocks 400 P 800 P
+09-Mar-01 Commodities revalued <Revalued> 800 P 1600 P
+09-Mar-01 Sample 3a As:Brokerage:Stocks 800 P 2400 P
+09-Apr-01 Commodities revalued <Revalued> 2400 P 4800 P
+09-Apr-01 Sample 4a As:Brokerage:Stocks -1600 P 3200 P
+10-Feb-01 Commodities revalued <Revalued> -2400 P 800 P
+10-Feb-01 Sample 2b As:Brokerage:Stocks 400 P 1200 P
+10-Mar-01 Commodities revalued <Revalued> 1200 P 2400 P
+10-Mar-01 Sample 3b As:Brokerage:Stocks 800 P 3200 P
+10-Apr-01 Commodities revalued <Revalued> 3200 P 6400 P
+10-Apr-01 Sample 4b As:Brokerage:Stocks -1600 P 4800 P
+>>>2
+=== 0
diff --git a/test/baseline/opt-master-account.test b/test/baseline/opt-master-account.test
new file mode 100644
index 00000000..1b571e6b
--- /dev/null
+++ b/test/baseline/opt-master-account.test
@@ -0,0 +1,15 @@
+bal --master-account=Master
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+ $-0.35
+ 0.350 VMMXX Master
+ 0.350 VMMXX Assets:Investments:Vanguard:VMMXX
+ $-0.35 Income:Dividends:Vanguard:VMMXX
+--------------------
+ $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-monthly.test b/test/baseline/opt-monthly.test
new file mode 100644
index 00000000..53942ee1
--- /dev/null
+++ b/test/baseline/opt-monthly.test
@@ -0,0 +1,220 @@
+reg --monthly books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 - 08-Jan-31 Expenses:Books $20.00 $20.00
+08-Feb-01 - 08-Feb-29 Expenses:Books $40.00 $60.00
+08-Mar-01 - 08-Mar-31 Expenses:Books $60.00 $120.00
+08-Apr-01 - 08-Apr-30 Expenses:Books $80.00 $200.00
+08-May-01 - 08-May-31 Expenses:Books $100.00 $300.00
+08-Jun-01 - 08-Jun-30 Expenses:Books $120.00 $420.00
+08-Jul-01 - 08-Jul-31 Expenses:Books $140.00 $560.00
+08-Aug-01 - 08-Aug-31 Expenses:Books $160.00 $720.00
+08-Sep-01 - 08-Sep-30 Expenses:Books $180.00 $900.00
+08-Oct-01 - 08-Oct-31 Expenses:Books $200.00 $1100.00
+08-Nov-01 - 08-Nov-30 Expenses:Books $220.00 $1320.00
+08-Dec-01 - 08-Dec-31 Expenses:Books $240.00 $1560.00
+09-Jan-01 - 09-Jan-31 Expenses:Books $20.00 $1580.00
+09-Feb-01 - 09-Feb-28 Expenses:Books $40.00 $1620.00
+09-Mar-01 - 09-Mar-31 Expenses:Books $60.00 $1680.00
+09-Apr-01 - 09-Apr-30 Expenses:Books $80.00 $1760.00
+09-May-01 - 09-May-31 Expenses:Books $100.00 $1860.00
+09-Jun-01 - 09-Jun-30 Expenses:Books $120.00 $1980.00
+09-Jul-01 - 09-Jul-31 Expenses:Books $140.00 $2120.00
+09-Aug-01 - 09-Aug-31 Expenses:Books $160.00 $2280.00
+09-Sep-01 - 09-Sep-30 Expenses:Books $180.00 $2460.00
+09-Oct-01 - 09-Oct-31 Expenses:Books $200.00 $2660.00
+09-Nov-01 - 09-Nov-30 Expenses:Books $220.00 $2880.00
+09-Dec-01 - 09-Dec-31 Expenses:Books $240.00 $3120.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-no-total.test b/test/baseline/opt-no-total.test
new file mode 100644
index 00000000..d1a11485
--- /dev/null
+++ b/test/baseline/opt-no-total.test
@@ -0,0 +1,10 @@
+bal --no-total
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+ 0.350 VMMXX Assets:Investments:Vanguard:VMMXX
+ $-0.35 Income:Dividends:Vanguard:VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-only.test b/test/baseline/opt-only.test
new file mode 100644
index 00000000..9728edae
--- /dev/null
+++ b/test/baseline/opt-only.test
@@ -0,0 +1,236 @@
+reg books --monthly --limit='amount > $100'
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Nov-01 - 08-Nov-30 Expenses:Books $220.00 $220.00
+08-Dec-01 - 08-Dec-31 Expenses:Books $240.00 $460.00
+09-Nov-01 - 09-Nov-30 Expenses:Books $220.00 $680.00
+09-Dec-01 - 09-Dec-31 Expenses:Books $240.00 $920.00
+>>>2
+=== 0
+reg books --monthly --only='amount > $100'
+>>>1
+08-Jun-01 - 08-Jun-30 Expenses:Books $120.00 $120.00
+08-Jul-01 - 08-Jul-31 Expenses:Books $140.00 $260.00
+08-Aug-01 - 08-Aug-31 Expenses:Books $160.00 $420.00
+08-Sep-01 - 08-Sep-30 Expenses:Books $180.00 $600.00
+08-Oct-01 - 08-Oct-31 Expenses:Books $200.00 $800.00
+08-Nov-01 - 08-Nov-30 Expenses:Books $220.00 $1020.00
+08-Dec-01 - 08-Dec-31 Expenses:Books $240.00 $1260.00
+09-Jun-01 - 09-Jun-30 Expenses:Books $120.00 $1380.00
+09-Jul-01 - 09-Jul-31 Expenses:Books $140.00 $1520.00
+09-Aug-01 - 09-Aug-31 Expenses:Books $160.00 $1680.00
+09-Sep-01 - 09-Sep-30 Expenses:Books $180.00 $1860.00
+09-Oct-01 - 09-Oct-31 Expenses:Books $200.00 $2060.00
+09-Nov-01 - 09-Nov-30 Expenses:Books $220.00 $2280.00
+09-Dec-01 - 09-Dec-31 Expenses:Books $240.00 $2520.00
+>>>2
+=== 0
+reg books --monthly --display='amount > $100'
+>>>1
+08-Jun-01 - 08-Jun-30 Expenses:Books $120.00 $420.00
+08-Jul-01 - 08-Jul-31 Expenses:Books $140.00 $560.00
+08-Aug-01 - 08-Aug-31 Expenses:Books $160.00 $720.00
+08-Sep-01 - 08-Sep-30 Expenses:Books $180.00 $900.00
+08-Oct-01 - 08-Oct-31 Expenses:Books $200.00 $1100.00
+08-Nov-01 - 08-Nov-30 Expenses:Books $220.00 $1320.00
+08-Dec-01 - 08-Dec-31 Expenses:Books $240.00 $1560.00
+09-Jun-01 - 09-Jun-30 Expenses:Books $120.00 $1980.00
+09-Jul-01 - 09-Jul-31 Expenses:Books $140.00 $2120.00
+09-Aug-01 - 09-Aug-31 Expenses:Books $160.00 $2280.00
+09-Sep-01 - 09-Sep-30 Expenses:Books $180.00 $2460.00
+09-Oct-01 - 09-Oct-31 Expenses:Books $200.00 $2660.00
+09-Nov-01 - 09-Nov-30 Expenses:Books $220.00 $2880.00
+09-Dec-01 - 09-Dec-31 Expenses:Books $240.00 $3120.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-output.test b/test/baseline/opt-output.test
new file mode 100644
index 00000000..49881fb3
--- /dev/null
+++ b/test/baseline/opt-output.test
@@ -0,0 +1,11 @@
+reg --output=/dev/stderr
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+>>>2
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+=== 0
diff --git a/test/baseline/opt-pager.test b/test/baseline/opt-pager.test
new file mode 100644
index 00000000..2a109ad7
--- /dev/null
+++ b/test/baseline/opt-pager.test
@@ -0,0 +1,11 @@
+reg --pager=cat
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-payee-as-account.test b/test/baseline/opt-payee-as-account.test
new file mode 100644
index 00000000..a9c95b2c
--- /dev/null
+++ b/test/baseline/opt-payee-as-account.test
@@ -0,0 +1,34 @@
+reg --account=payee
+<<<
+2008/01/01 * (100) January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 (101) End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 * (102) February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 (103) End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 * March
+ Expenses:Books $30.00
+ Assets:Cash
+>>>1
+08-Jan-01 January January $10.00 $10.00
+08-Jan-01 January January $-10.00 0
+08-Jan-31 End of January End of January $10.00 $10.00
+08-Jan-31 End of January End of January $-10.00 0
+08-Feb-01 February February $20.00 $20.00
+08-Feb-01 February February $-20.00 0
+08-Feb-28 End of February End of February $20.00 $20.00
+08-Feb-28 End of February End of February $-20.00 0
+08-Mar-01 March March $30.00 $30.00
+08-Mar-01 March March $-30.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-payee-width.test b/test/baseline/opt-payee-width.test
new file mode 100644
index 00000000..a5f61e87
--- /dev/null
+++ b/test/baseline/opt-payee-width.test
@@ -0,0 +1,11 @@
+reg --payee-width=40
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-payee.test b/test/baseline/opt-payee.test
new file mode 100644
index 00000000..56ee0cde
--- /dev/null
+++ b/test/baseline/opt-payee.test
@@ -0,0 +1,11 @@
+reg --payee='account_base + ":" + commodity'
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 VMMXX:VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+07-Feb-02 VMMXX:$ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-pending.test b/test/baseline/opt-pending.test
new file mode 100644
index 00000000..9a3507be
--- /dev/null
+++ b/test/baseline/opt-pending.test
@@ -0,0 +1,200 @@
+reg --pending
+<<<
+2008/01/01 * January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 ! February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 * March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ * Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ * Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ ! Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ ! Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Feb-01 February Expenses:Books $20.00 $20.00
+ Assets:Cash $-20.00 0
+08-May-01 May Assets:Cash $-50.00 $-50.00
+08-May-31 End of May Assets:Cash $-50.00 $-100.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-percent.test b/test/baseline/opt-percent.test
new file mode 100644
index 00000000..1adb0a8a
--- /dev/null
+++ b/test/baseline/opt-percent.test
@@ -0,0 +1,94 @@
+bal --percent
+<<<
+2008/01/11 LIAT
+ Expenses:Travel:Airfare $40.00
+ Liabilities:MasterCard
+
+2008/01/14 cheaptickets.com
+ Expenses:Travel:Airfare $182.19
+ Liabilities:MasterCard
+
+2008/02/05 CTX
+ Expenses:Travel:Auto $240.38
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/22 BUDGET RENT-A-CAR
+ Expenses:Travel:Auto $40.59
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/08/08 BCIS I-131 FILING FEE-
+ Expenses:Travel:Passport $170.00
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/22 AGNT FEE
+ Expenses:Travel:Airfare $70.00
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 LIAT 1974 LIMITED
+ Expenses:Travel:Airfare $418.34
+ Liabilities:MasterCard
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+>>>1
+ 100.00% Assets:Checking
+ 100.00% Expenses:Travel
+ 92.15% Airfare
+ 3.13% Auto
+ 4.72% Passport
+ 100.00% Liabilities:MasterCard
+>>>2
+=== 0
diff --git a/test/baseline/opt-period.test b/test/baseline/opt-period.test
new file mode 100644
index 00000000..09e7e355
--- /dev/null
+++ b/test/baseline/opt-period.test
@@ -0,0 +1,290 @@
+reg -p "january 2008"
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Expenses:Books $10.00 $10.00
+ Liabilities:Cards $10.00 $20.00
+ Assets:Cash $-20.00 0
+08-Jan-31 End of January Expenses:Books $10.00 $10.00
+ Liabilities:Cards $10.00 $20.00
+ Assets:Cash $-20.00 0
+>>>2
+=== 0
+reg -p "monthly january 2008"
+>>>1
+08-Jan-01 - 08-Jan-31 Assets:Cash $-40.00 $-40.00
+ Expenses:Books $20.00 $-20.00
+ Liabilities:Cards $20.00 0
+>>>2
+=== 0
+reg -p "weekly january 2008"
+>>>1
+08-Jan-01 - 08-Jan-05 Assets:Cash $-20.00 $-20.00
+ Expenses:Books $10.00 $-10.00
+ Liabilities:Cards $10.00 0
+08-Jan-29 - 08-Jan-31 Assets:Cash $-20.00 $-20.00
+ Expenses:Books $10.00 $-10.00
+ Liabilities:Cards $10.00 0
+>>>2
+=== 0
+reg -p "yearly 2008"
+>>>1
+08-Jan-01 - 08-Dec-31 Assets:Cash $-3120.00 $-3120.00
+ Expenses:Books $1560.00 $-1560.00
+ Liabilities:Cards $1560.00 0
+>>>2
+=== 0
+reg -p "from 2009/11/01"
+>>>1
+09-Nov-01 November Expenses:Books $110.00 $110.00
+ Liabilities:Cards $110.00 $220.00
+ Assets:Cash $-220.00 0
+09-Nov-30 End of November Expenses:Books $110.00 $110.00
+ Liabilities:Cards $110.00 $220.00
+ Assets:Cash $-220.00 0
+09-Dec-01 December Expenses:Books $120.00 $120.00
+ Liabilities:Cards $120.00 $240.00
+ Assets:Cash $-240.00 0
+09-Dec-31 End of December Expenses:Books $120.00 $120.00
+ Liabilities:Cards $120.00 $240.00
+ Assets:Cash $-240.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-plot-amount-format.test b/test/baseline/opt-plot-amount-format.test
new file mode 100644
index 00000000..9c5484af
--- /dev/null
+++ b/test/baseline/opt-plot-amount-format.test
@@ -0,0 +1,10 @@
+reg -j --plot-amount-format='X %(format_date(date, "%Y-%m-%d")) Y %(quantity(scrub(display_amount)))\n'
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+X 2007-02-02 Y 0.35
+X 2007-02-02 Y -0.35
+>>>2
+=== 0
diff --git a/test/baseline/opt-plot-total-format.test b/test/baseline/opt-plot-total-format.test
new file mode 100644
index 00000000..1065c5ce
--- /dev/null
+++ b/test/baseline/opt-plot-total-format.test
@@ -0,0 +1,10 @@
+reg -J --plot-total-format='X %(format_date(date, "%Y-%m-%d")) Y %(quantity(scrub(display_amount)))\n'
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+X 2007-02-02 Y 0.35
+X 2007-02-02 Y -0.35
+>>>2
+=== 0
diff --git a/test/baseline/opt-price.test b/test/baseline/opt-price.test
new file mode 100644
index 00000000..06cc7751
--- /dev/null
+++ b/test/baseline/opt-price.test
@@ -0,0 +1,47 @@
+reg equities
+<<<
+2008/01/01 * Purchase Apple shares
+ Equities 1000 AAPL @ $2
+ Cash $-2000
+
+2008/06/30 * Sell some Apple shares
+ Cash $1250
+ Equities -500 AAPL {$2} @ $2.50
+ Income:Gains $-250
+
+P 2008/10/01 02:18:02 AAPL $3
+P 2009/01/31 02:18:02 AAPL $4
+P 3000/01/01 02:18:02 APPL $100
+>>>1
+08-Jan-01 Purchase Apple shares Equities 1000 AAPL 1000 AAPL
+08-Jun-30 Sell some Apple sha.. Equities -500 AAPL 500 AAPL
+>>>2
+=== 0
+reg -B equities
+>>>1
+08-Jan-01 Purchase Apple shares Equities $2000 $2000
+08-Jun-30 Sell some Apple sha.. Equities $-1250 $750
+>>>2
+=== 0
+reg --end 2009/06/26 -V equities
+>>>1
+08-Jan-01 Purchase Apple shares Equities $2000 $2000
+08-Jun-30 Commodities revalued <Revalued> $500 $2500
+08-Jun-30 Sell some Apple sha.. Equities $-1250 $1250
+09-Jun-26 Commodities revalued <Revalued> $750 $2000
+>>>2
+=== 0
+reg --end 2009/06/26 -G equities
+>>>1
+08-Jan-01 Purchase Apple shares Equities 0 0
+08-Jun-30 Commodities revalued <Revalued> $500 $500
+08-Jun-30 Sell some Apple sha.. Equities 0 $500
+09-Jun-26 Commodities revalued <Revalued> $750 $1250
+>>>2
+=== 0
+reg -I equities
+>>>1
+08-Jan-01 Purchase Apple shares Equities $2000 $2000
+08-Jun-30 Sell some Apple sha.. Equities $-1000 $1000
+>>>2
+=== 0
diff --git a/test/baseline/opt-pricedb-format.test b/test/baseline/opt-pricedb-format.test
new file mode 100644
index 00000000..e2c26f5f
--- /dev/null
+++ b/test/baseline/opt-pricedb-format.test
@@ -0,0 +1,21 @@
+pricedb --pricedb-format='P %(date) %(scrub(display_amount))\n'
+<<<
+D $1,000.00
+
+P 2009/01/01 13:30:00 AAPL $10.00
+P 2009/01/01 14:30:00 AAPL $20.00
+P 2009/01/01 15:30:00 AAPL $30.00
+P 2009/01/01 16:30:00 AAPL $40.00
+P 2009/02/01 17:30:00 AAPL $50.00
+
+2009/03/01 Purchase
+ Assets:Brokerage 100 AAPL
+ Income
+>>>1
+P 2009/01/01 $10.00
+P 2009/01/01 $20.00
+P 2009/01/01 $30.00
+P 2009/01/01 $40.00
+P 2009/02/01 $50.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-prices-format.test b/test/baseline/opt-prices-format.test
new file mode 100644
index 00000000..8a83ad5f
--- /dev/null
+++ b/test/baseline/opt-prices-format.test
@@ -0,0 +1,21 @@
+prices --prices-format='%(datetime) %(scrub(display_amount))\n'
+<<<
+D $1,000.00
+
+P 2009/01/01 13:30:00 AAPL $10.00
+P 2009/01/01 14:30:00 AAPL $20.00
+P 2009/01/01 15:30:00 AAPL $30.00
+P 2009/01/01 16:30:00 AAPL $40.00
+P 2009/02/01 17:30:00 AAPL $50.00
+
+2009/03/01 Purchase
+ Assets:Brokerage 100 AAPL
+ Income
+>>>1
+2009/01/01 13:30:00 $10.00
+2009/01/01 14:30:00 $20.00
+2009/01/01 15:30:00 $30.00
+2009/01/01 16:30:00 $40.00
+2009/02/01 17:30:00 $50.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-print-format.test b/test/baseline/opt-print-format.test
new file mode 100644
index 00000000..103ceb1e
--- /dev/null
+++ b/test/baseline/opt-print-format.test
@@ -0,0 +1,10 @@
+print --print-format='%(amount)\n'
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+0.350 VMMXX {$1.00} [2007/02/02]
+$-0.35
+>>>2
+=== 0
diff --git a/test/baseline/opt-quantity.test b/test/baseline/opt-quantity.test
new file mode 100644
index 00000000..5de92e84
--- /dev/null
+++ b/test/baseline/opt-quantity.test
@@ -0,0 +1,11 @@
+reg --quantity
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-quarterly.test b/test/baseline/opt-quarterly.test
new file mode 100644
index 00000000..b96e11ff
--- /dev/null
+++ b/test/baseline/opt-quarterly.test
@@ -0,0 +1,204 @@
+reg --quarterly books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 - 08-Mar-31 Expenses:Books $120.00 $120.00
+08-Apr-01 - 08-Jun-30 Expenses:Books $300.00 $420.00
+08-Jul-01 - 08-Sep-30 Expenses:Books $480.00 $900.00
+08-Oct-01 - 08-Dec-31 Expenses:Books $660.00 $1560.00
+09-Jan-01 - 09-Mar-31 Expenses:Books $120.00 $1680.00
+09-Apr-01 - 09-Jun-30 Expenses:Books $300.00 $1980.00
+09-Jul-01 - 09-Sep-30 Expenses:Books $480.00 $2460.00
+09-Oct-01 - 09-Dec-31 Expenses:Books $660.00 $3120.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-raw.test b/test/baseline/opt-raw.test
new file mode 100644
index 00000000..f9294724
--- /dev/null
+++ b/test/baseline/opt-raw.test
@@ -0,0 +1,11 @@
+print --raw
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>2
+=== 0
diff --git a/test/baseline/opt-real.test b/test/baseline/opt-real.test
new file mode 100644
index 00000000..b406f29a
--- /dev/null
+++ b/test/baseline/opt-real.test
@@ -0,0 +1,11 @@
+reg --real
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ (Liabilities:Cards) $10.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Expenses:Books $10.00 $10.00
+ Assets:Cash $-10.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-register-format.test b/test/baseline/opt-register-format.test
new file mode 100644
index 00000000..2384b6e2
--- /dev/null
+++ b/test/baseline/opt-register-format.test
@@ -0,0 +1,10 @@
+reg --register-format='%(amount)\n'
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+0.350 VMMXX {$1.00} [2007/02/02]
+$-0.35
+>>>2
+=== 0
diff --git a/test/baseline/opt-related-all.test b/test/baseline/opt-related-all.test
new file mode 100644
index 00000000..645f8a91
--- /dev/null
+++ b/test/baseline/opt-related-all.test
@@ -0,0 +1,14 @@
+reg --related-all credit
+<<<
+2009/06/18 This is a Test
+ Expenses:Food $20.00
+ Expenses:Tips $2.00
+ Expenses:Tax $3.00
+ Liabilities:Credit
+>>>1
+09-Jun-18 This is a Test Expenses:Food $20.00 $20.00
+ Expenses:Tips $2.00 $22.00
+ Expenses:Tax $3.00 $25.00
+ Liabilities:Credit $-25.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-related.test b/test/baseline/opt-related.test
new file mode 100644
index 00000000..576bc9d2
--- /dev/null
+++ b/test/baseline/opt-related.test
@@ -0,0 +1,13 @@
+reg --related credit
+<<<
+2009/06/18 This is a Test
+ Expenses:Food $20.00
+ Expenses:Tips $2.00
+ Expenses:Tax $3.00
+ Liabilities:Credit
+>>>1
+09-Jun-18 This is a Test Expenses:Food $20.00 $20.00
+ Expenses:Tips $2.00 $22.00
+ Expenses:Tax $3.00 $25.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-revalued-only.test b/test/baseline/opt-revalued-only.test
new file mode 100644
index 00000000..5135b80d
--- /dev/null
+++ b/test/baseline/opt-revalued-only.test
@@ -0,0 +1,59 @@
+reg --market --revalued-only stocks
+<<<
+2009/01/01 Sample 1a
+ Assets:Brokerage:Stocks 100 S
+ Assets:Brokerage:Cash -100 P
+
+P 2009/01/01 00:00:00 S 2 P
+
+2009/02/01 Sample 2a
+ Assets:Brokerage:Stocks 100 S @ 1 P
+ Assets:Brokerage:Cash
+
+P 2009/02/01 00:00:00 S 4 P
+
+2009/03/01 Sample 3a
+ Assets:Brokerage:Stocks 100 S @@ 100 P
+ Assets:Brokerage:Cash
+
+P 2009/03/01 00:00:00 S 8 P
+
+2009/04/01 Sample 4a
+ Assets:Brokerage:Cash 100 P
+ Assets:Brokerage:Stocks -100 S {1 P}
+
+P 2009/04/01 00:00:00 S 16 P
+
+; In this usage case, the top amount is always secondary
+; 2010/01/01 Sample 1b
+; Assets:Brokerage:Cash -100 P
+; Assets:Brokerage:Stocks 100 S
+;
+; P 2010/01/01 00:00:00 S 2 P
+
+2010/02/01 Sample 2b
+ Assets:Brokerage:Cash
+ Assets:Brokerage:Stocks 100 S @ 1 P
+
+P 2010/02/01 00:00:00 S 4 P
+
+2010/03/01 Sample 3b
+ Assets:Brokerage:Cash
+ Assets:Brokerage:Stocks 100 S @@ 100 P
+
+P 2010/03/01 00:00:00 S 8 P
+
+2010/04/01 Sample 4b
+ Assets:Brokerage:Stocks -100 S {1 P}
+ Assets:Brokerage:Cash 100 P
+
+P 2010/04/01 00:00:00 S 16 P
+>>>1
+09-Feb-01 Commodities revalued <Revalued> 200 P 400 P
+09-Mar-01 Commodities revalued <Revalued> 800 P 1600 P
+09-Apr-01 Commodities revalued <Revalued> 2400 P 4800 P
+10-Feb-01 Commodities revalued <Revalued> -2400 P 800 P
+10-Mar-01 Commodities revalued <Revalued> 1200 P 2400 P
+10-Apr-01 Commodities revalued <Revalued> 3200 P 6400 P
+>>>2
+=== 0
diff --git a/test/baseline/opt-revalued.test b/test/baseline/opt-revalued.test
new file mode 100644
index 00000000..b68b256b
--- /dev/null
+++ b/test/baseline/opt-revalued.test
@@ -0,0 +1,66 @@
+reg --market --revalued stocks
+<<<
+2009/01/01 Sample 1a
+ Assets:Brokerage:Stocks 100 S
+ Assets:Brokerage:Cash -100 P
+
+P 2009/01/01 00:00:00 S 2 P
+
+2009/02/01 Sample 2a
+ Assets:Brokerage:Stocks 100 S @ 1 P
+ Assets:Brokerage:Cash
+
+P 2009/02/01 00:00:00 S 4 P
+
+2009/03/01 Sample 3a
+ Assets:Brokerage:Stocks 100 S @@ 100 P
+ Assets:Brokerage:Cash
+
+P 2009/03/01 00:00:00 S 8 P
+
+2009/04/01 Sample 4a
+ Assets:Brokerage:Cash 100 P
+ Assets:Brokerage:Stocks -100 S {1 P}
+
+P 2009/04/01 00:00:00 S 16 P
+
+; In this usage case, the top amount is always secondary
+; 2010/01/01 Sample 1b
+; Assets:Brokerage:Cash -100 P
+; Assets:Brokerage:Stocks 100 S
+;
+; P 2010/01/01 00:00:00 S 2 P
+
+2010/02/01 Sample 2b
+ Assets:Brokerage:Cash
+ Assets:Brokerage:Stocks 100 S @ 1 P
+
+P 2010/02/01 00:00:00 S 4 P
+
+2010/03/01 Sample 3b
+ Assets:Brokerage:Cash
+ Assets:Brokerage:Stocks 100 S @@ 100 P
+
+P 2010/03/01 00:00:00 S 8 P
+
+2010/04/01 Sample 4b
+ Assets:Brokerage:Stocks -100 S {1 P}
+ Assets:Brokerage:Cash 100 P
+
+P 2010/04/01 00:00:00 S 16 P
+>>>1
+09-Jan-01 Sample 1a As:Brokerage:Stocks 200 P 200 P
+09-Feb-01 Commodities revalued <Revalued> 200 P 400 P
+09-Feb-01 Sample 2a As:Brokerage:Stocks 400 P 800 P
+09-Mar-01 Commodities revalued <Revalued> 800 P 1600 P
+09-Mar-01 Sample 3a As:Brokerage:Stocks 800 P 2400 P
+09-Apr-01 Commodities revalued <Revalued> 2400 P 4800 P
+09-Apr-01 Sample 4a As:Brokerage:Stocks -1600 P 3200 P
+10-Feb-01 Commodities revalued <Revalued> -2400 P 800 P
+10-Feb-01 Sample 2b As:Brokerage:Stocks 400 P 1200 P
+10-Mar-01 Commodities revalued <Revalued> 1200 P 2400 P
+10-Mar-01 Sample 3b As:Brokerage:Stocks 800 P 3200 P
+10-Apr-01 Commodities revalued <Revalued> 3200 P 6400 P
+10-Apr-01 Sample 4b As:Brokerage:Stocks -1600 P 4800 P
+>>>2
+=== 0
diff --git a/test/baseline/opt-seed.test.save b/test/baseline/opt-seed.test.save
new file mode 100644
index 00000000..48ca7d13
--- /dev/null
+++ b/test/baseline/opt-seed.test.save
@@ -0,0 +1,432 @@
+generate --seed=10
+<<<
+>>>1
+2186/12/04=1987/04/07 (gxB) Xcm0wJS7fGh07
+ ; K93x8n5028OV19:n9zv0ksC
+ [MIdo:Y377U9xhRjxQaFFk37:aEaw66xn:9ss914] 411126pQ @ ozgYxo0.578679
+ ; n1:1Bm38PMy6FO51R58pWhXmc1HN08Umw8T
+ (X:S) -936200r @ nijv235713
+ ; j7zUn1U8UPStcn46 72dpS5vd9d2oxQk:R
+ C:27lps3E
+
+2186/12/09=1987/04/08 (B7xDea) yA6fOo:q0A6IaA7v ; LB:l
+ cro FhdXRF:nROGw1H8PqY10Jg 3FQRrcX07 -733399YmHWf @ 0.640803LMtLP ; dVmRkOR
+ [Z2t:31I:2ox:81NC28A0] 263844DKa ; h4I8M355
+ B0VD1MI2073MblRrsPV64O9 EEMQ 816045 @ 0.499731hzxnl ; qAsYFCY
+ [b1X09LHz:AkK5G] U -785951
+ ; gJy3hZ4g75vf84:9Rz R 6Vpy11ZJ:24K m U:Y
+ DI7 3 ; H64
+
+2186/12/11=1987/04/12 ! (Xu:Eo) Cx4o2an 3Upa0Fll:nDjT461:y ; uzZ5uQlLWR4
+ [XKU2Jj6:p6I5kVSPv 3vpG:ShyKRF:dv8y] Tgojw -14862.9
+ [SPOiCDS5Zg:t:Q7vMF01n8P:7h1i] qXxf 437098 @ BmJ866903
+ [reGXB0LK38iD5FM zWxl PUW:eI5F21EN80e] acLq947715
+ (NA LA 11uhxP8y7oBBgXZQ45lwPb1) 14641.5sndK @ 44.2184885 Cw
+ ; P4158:i1xa1eoHUHeF1pS8
+ [CMs:8Yz9t7H1aF3qN] qt250589
+ (B0T) a-715047 @ 0.946357 Ac
+ ; PeUU8DYH3 BxS Uu9y:YfU0isX6ly:sZO6S2xpN
+ V:60vuV
+
+2186/12/12=1987/04/14 * (OEWOu) SLGS
+ ; AuFLS1XOW:z04:gwQ2
+ (VjI Tm79d6) -93666.5xuIH ; A9
+ [UF3xXu kOA ERwiQOh aprUp9gM] -103361jSZeo @ 564002 iJOXN
+ (EzJ 65T295) QCaR134452 @ RuLEEw 0.6292982
+ ; M8916aJx5C7:G9U0I:y4t68
+ W oUJuq66YfULC1 CW95nX2VZch2:qK992pM3fhy manJj -209990 @ c 536098
+ ; yzOvW 28W99zgmW9Y9:j:5w:1:gIX
+ rNUT0rM:rBsW:P87ZVn3d8X
+
+2186/12/17=1987/04/15 * (F7u) sZ:c vZ8U3Sr705
+ T2DT75mS9x7 W727197 @ 1.264289dfiel
+ (Z X9E8W16j8:521) zPFS-334854
+ ; RkIZ27O30b8:yf0pXU
+ (jAmK) 426564AO @ SemS 421251
+ ER lq6N3 q 3317.11 @ RAAii 254.77207569
+ ixS
+
+2186/12/21 * (EVhm) fnA 7GRR710:8:FhSlZRc:4L5J74Q RnH9H4v ; N2
+ (dGg77g:i40RE7J3KnxNNHB0E 7) 262042 z
+ ; N3V98V827I:qaJ2U4E5IR tpHJw0J699:f
+ M8:vCvoagZmVL1Y:543:eucH98:Q 222936 aZtSl @ 1.851056rQWi
+ ; Os2Z7rnOU11Y9vm8pGNvTuK
+ [KWybHT:s] Zc -395512 @ 673430 Q
+ ; JDK FpB 6g 5dBDa
+ [Tk:B1257JrD9:LgqbzmH8GQ] UaS-222545 ; uiM6
+ u335Ic
+
+2186/12/27 ! (GS) EJ99iD7cHek7EJp5aoFYIXz2Wx:hTSIPWjP
+ [rRlyn:21:Jcu292Ea] YuOJ-77111.5 @ ys9.708928
+ ; EI309:2D t66H6NzNv c AXmMzeF4:kR
+ [jn 58DWi8DwD48Ee3:05qkh38Y8754VMaC80OD] 205960LdQ @ iiB 2.206851 ; vTJ9I oLQ9KF1l
+ [zqBE2yO1UWmgM4BL:A9Do4EffRd8V:io] w-53161.6 @ 350764 UclkLw
+ g:R000qI3C 746879 juFf @ hlN448555
+ ; x5:1OGWm WY9Fdtu:8rD09k1:5z 1:8Y:xQ11I
+ A43J7Yjx6xKhN0:TjP ; f:l8Q 1L7RjfBQ
+
+2186/12/29 * (R3:UJ) hN K3YTd:0y:42Ze9ObAaT lgx:yJ:ir1j ; xIIL05IE2p3
+ [y jLigz uChQA Eg4UEf0 70B:94:i4DqcQq] iyg895724 @ 0.510892 mCiSp
+ w8C 7Hx8Rq91QS6z:7b -331711 vDTIl
+ U0987:F:4DTh6V F6 Rkp3p1 CTDATK-782095
+ [kG7R6F:9jPxChWVOObKg045AE80hc87FW] 252408ViNkjs
+ jHM I5:Y
+
+2187/01/02=1987/04/20 (oCi) coD:3Y1ZEF79r:C086
+ ; q:Gk:331:S9 o:0CREm
+ (bML5K:jl7ntsH213:Q:1BjWS8Lrqp:3 qSg2 93) SgXoC 338602
+ [mr7R wS405TMYlnq7:Jx:e7:Qv8uElrM01Ww] 596325 IEVnen
+ ; V220WkzjO p:eVRrzBl473Nht:26U
+ o1h:E
+ ; n:34:ThQmLaTUfgbrNm:71p1C9
+
+2187/01/03=1987/04/24 * (e) S:8O8F8P4672h6 ; UEJwkn
+ (iA:R70:9:Wzp4x:v9skm) SXV 822239
+ o6Vo3X:HmQ:8s94RFZ8:fbxJYY2:xy6 wE 129507 @ 7.102689 hq
+ ; T:Dr0SwdlwU:3gn49
+ TDM8vS3 4:l497yk2f2 d307311 @ 0.344104 xOqmt
+ ; hrZn9 5BaTBOkT16 y:65f848liI558:f9
+ ADHTI7b:417f9NC p:81Dn:dd:2t58QPvkr6 280677 ewaJgw @ OhuZ248193 ; US178U5:E2P
+ JvY8mjt0 p1F ; Er nO
+
+2187/01/09 (u) I55B7BN7Nic0Xf7l:enK6:wZEp
+ [u7n1K7hy3kMKbPG hL] pIYM -959467
+ [Xe3P2P:oUoMA1slU09R] -544505SfH @ 852228 OkXknF
+ ; z uE9:xQ53Sy0 s3p53voVFV:bOP2mL9K4hBf:24
+ YJ5N:el1lEP1rksmQ4af8vXzlix:87 oXtoLV-494724
+ [f28 6:EG5sn 6clN E:689EhZ6rljIS9A05HB] -592178TcaIqX @ 0.52632KqgxJY
+ oiMz51lFxbnN
+
+2187/01/10 * (f:YKS) b152q
+ ; l0728x5Ep97f405oy5sTr4j
+ (X2l:yjc3P5Jf0R8slv7fn:DWa0HB63yUBY) -637008UW
+ b -526513qGuvC
+ (P9QJnILJLlK20j9) VJx -237745
+ ; H0:S1m6o:kpqGBmr0jn4yGp0PPx63680Bo
+ [JpVMi82HvZ8Cjn8R] jVSSg-913619 @ 0.808966 yoc
+ ; jYk3X58298IFBV7M TH3WN4n l0:x73agt4z
+ (HU 0M:e3A:030XdN3:8g) 243401kRXr @ eW 346761
+ ; V6tnx1GMt6B0iT5DL9
+ Eh EjQL:5Rj:68NZ42kd 16djH k883779 @ 652143 KQK
+ hlxM319I2412y
+
+2187/01/14 (p7NK) i56
+ (E0V bMA) -901145n
+ ; I0G5G9axvs32G0R19D72Nj
+ c:6q9 dM:73:5Nc1p5g:c0 q -764271.00 @ 0.310259Pwv
+ [Nf2:jSoF:X79mOgTa:t4 CC8903Ug 0cf Gv4w] -345268RzzzmL @ e 1.692647
+ ; R:KT0Y:WIkiD3UB2Fu6:CK5X6G6K1
+ (d) PDGe 828999
+ ; iFk6G5XkFII6739 31Dq2Qde25a:vfvRL0
+ NDODeT1ud913r9L:s7JDMkkGwNHEoac ; FyMDFsNG
+
+2187/01/20=1987/04/29 ! (uvZ) C79:n5SB4r
+ OV35363j:REM:JjkW -996837ufeCSQ @ 0.47472dq ; EqA:SE2QJpd20a
+ [JTaWorK:018RpRg1y23Eh2FzS:o84BimcBP] 644258 VmNxi
+ uh:l8fPO05YCYi053
+
+2187/01/23 * (M) p4yw23Z7z708H2t 1d108W509F XtQHd
+ ; JrdATcORmZ7F4:RilGAo4nPERSla K8:q319
+ (pgNXjW:7:w c6434RmZg9x39A QgUoDd8NZ) SUO 203170
+ [ob] DHAra-72498.6 @ 2.7968954yeCD
+ ; xTxkz:Qo:27 6146k0
+ [o:1wP7Q2] 77384 dQolH @ 492890 l ; H:d6 Yu
+ [vhjm6FF] -597065 iBP @ brzs0.0717997
+ B1V:H4agb9:aLP9235e2b
+
+2187/01/29 (KQhu) Q7x65f8ls25W88oyPR1H56I
+ (lX 0:3ZQ8e:f:We0b4lAUvFl7lf5x208) 383456kQrwsT
+ ; wa0f6v8ZJ7:on7T
+ [She:qWK1Qaijt7B5ua0] kniumo499909
+ ; Z:CP:A5hK5uN4JI7FMqS3V:vyVS2
+ [Y68R:A5N] 798458a
+ ; x:26gTlXF1:7:R6BMewcn:H:N8UXE
+ (QfdF:4GLhMy) b-547602
+ ; b aPGwAfp Qx:m952ctx495
+ [utb8nOU0r9N] mLHbE223101
+ A6f1R:zEq0Vea3gsKnC9:06 a224 ZmNQ 774115 @ 892757 OQv
+ ; X6g:0Ka:8E735uVV
+ W6zw11QYbiE3awi1d A
+ ; pXFvBnAu8E77qcw:ZUlwkWV5lZ:VkC3:5gZyaERW
+
+2187/02/01=1987/05/01 ! (wv5i) f6n2pmhOP77oyv6:IG5j0TEk9v5pXP9810s
+ V 5w Po:lVghM1g4t3BXKy B B:1Zz gT -123047
+ S3j:Aj4s 791849I
+ [B9:WfB9KIt4vLU51:Jm99I6Q125dMRIqx66vC5z2] 242497 A @ 583994 uXRfdk ; p5H8:j:o:fES
+ lS7d:q -106717 iefO
+ sj
+
+2187/02/04 (s) Z1yWLuX5yE4h:xT0X0Ga:o7:8T:0BbAvP46
+ ; X79u5:K mYCw9Utl
+ (uE:h:1jzdLirp r gP5Z:AF:79I) -711627oRDqJP @ CLpS1.184335 ; DUx7WX5j4nX
+ [t2xBfs53KgY vP:XxCk2bmJC92 3Sx5U4] 313034 GINL
+ ; lLpf64qmRAVY7J943jaE:c:l 4570l4:P
+ u8 84Cpd e3
+ ; g a m05HNW45pto sn0pJPv0U9r5bfT
+
+2187/02/07 (aj:5) X7rkc3PjvxTL l
+ V8aoGZ8p IL 50587.5vBeRJ
+ M6Ai3R:Q 325120 O
+ J5EUo35CK:qrg4E:V RznCQB3:q8MX1tX0CDyp 975643CDIcM @ 855572Twu ; bf5 A
+ [TM5Z] 913463 oimIl
+ YI8S9:X:C6zA 75
+
+2187/02/08=1987/05/03 (u5N2W) X2Lbql6n O:z2U1WB0 iDB8N0:4O286Be4h5q5
+ [q95j7F] Z -886734 @ 931353 bNt ; u0G KuFLh nq68
+ (Y:3LOBz1:S:nA7B) wwL-880685 @ 960618G
+ X9:gud7uR5Qxth7:f1Q0
+ ; F2lUncNAoUU4hWY DVe
+
+2187/02/10 * (E) n07K0X69w9Lm5n:Kas2ErCM6l4 48cR18Y:SnV
+ [R Cv H:6SpHO6:l63Gq:20JXImfc] -667443 y ; Kv
+ [mI9ZfM02qNaD8] 668500 RYSLl @ ddu0.19124
+ d:BPcI1lYVW9CcA6yL:4lhaK6ID717
+ ; N8Ix1H95urPX pLL5m:vz1mg:e A8
+
+2187/02/13=1987/05/05 ! (c) Bb7b10:fG8C 6 6Wx1l
+ [Ef] -85775.1dN @ 315212ejCU
+ (wLjq:0601Iqx:96 HF) 658188HKt
+ suu2OqWMY6sJFv:xm:Tx -638358 jnDT
+ [g:9S f8OoiA87l0I4Kqx3] -601167p @ 43014.8 aLq
+ ; S:2T:i:IzbT:bNP5snh:2Pk:5nu
+ lN 8U973P3983pe32X:A:219N:1
+ ; W:0 BO yy8:w8evC7YmboP ghx2:J9Xo
+
+2187/02/18 * (AN) oUwsLl:0Mm6p66d4leuup0:2x
+ ; c 5kp7U8G1k4:3qemxEP9IIYN8YUxA:8I9q
+ ysc8Prp:BAO3:NmJPIpZli -863446K @ VQ568439 ; tA6
+ (I 4u8PI1L81v:aOP1QE74d 1DDZBY e7) Xl -571100
+ ; C3SV V0zIpW0K6O:Uy1d:Q7dvwz:o5B EQ Nh
+ (L bD:5l2K650y8i9Ja) d-942453
+ ; FjCMw2cXC3T5S1 P7d:d:O63BwR6O
+ (qYLNQ:ApC) P -371484 @ WLbB 716482
+ ; LkfG:wU7kt 6Ayo9H9 ho
+ (AH7Z266:lo9126ooP:ok6IqMf0) -695058SXInq @ Abz 913865
+ ; Lqh76O:sSk3Y9zRR
+ [f:z:n2:bO7fwc230R:2Y7fjX9Yqq:649] RkqnLo 249887 @ vTD 1.7248
+ IW0M187 Ub
+ ; u4h0r2cSYS1kHW 9j6FyRk1y
+
+2187/02/20=1987/05/06 (W95) k
+ [TDrC8nTiD:r4Dx9177sQJvd16Ed9SvU mrE81:oD] bipfJi -629380
+ [cD2:Hy:DV6zL a647Aq7Pp71gTruf:0] BzPmpg 612835
+ ; W3FiFcDe53HIm789:kQN
+ (nP6CPmJd9g7jS72M 41q:t V5ltrdUx169Zu28) 975397 shihH
+ qT7c6 -655081 BXPPc @ Ya 872226 ; yIX7OGx
+ (mQSZ) 426510 zcBER @ tsnr606449 ; cJS:z12J4QvOA
+ [Yjfk:FmxjrVAa278WBuv5:50eG7w] Xake56556.8
+ uM61VJYWHmmS2swhTs1624firiH7MjO5Z5 M0Y
+
+2187/02/23=1987/05/08 ! (R) Dg8:279q:90GKH7:pq3WN kXi:C:4qf76
+ ; NlnAoFwM C7d3KH8A:6:lHr o8kxh6N130jo:kJ
+ VI6YZ -597872tIjW
+ (e:81C4:oO swE5f 9l:d9) wUna-360797 ; mJ y8mI
+ (a2y 6:iZLCdeW t10vqB7n3YN:7) 272995 NcKRN
+ ; taqP:G6i 8ePbU7GD59:r6iS
+ E46j:t7f50rjzczn -420867In
+ (qfK1A qE9SAMwwY:RbfPDS) lAcJ136457 ; AJ7hu5lhG2Q
+ m9GnlWF:P 2e6300i0o:K 930528Om @ 127927Rq
+ ; YN86XuS17Ax6fBYw8:FZB
+ v89c7V90x898JVnHFV:i28l3mMf1xTU:Bo7iJ2d ; YHqY
+
+2187/02/24=1987/05/12 * (t87o) mjrM4MyN8oKdpS4s
+ ; dh4gFZgBk5z29g2F44zT5I9g58Xpo:AYe9u3
+ (uQI843zXpD9vK6l2dc93) VDZfau695674 @ 1.395381tJ
+ A:UT:2t 4BPcec8xuFg Qb2sRg79Wt -715837BWwCJu
+ i uRN1hvI8
+ ; Yh 2:snU9F5u0Q7:eT507nI3mN oSE8MkeZ0kPnF
+
+2187/03/02 (JaP) M:j9:DzCYyd:M V6 ; YCd5tl8gTY7r
+ KWu6Q vju54Wqg:Hajy3K5 699037PsAu @ 0.0432019 dmmsRU
+ gm:9:Uf:t:jZCaY8ZoPqd UB:qjC5OtR v2y -65372.2DRpj @ aPXbpG0.66845387
+ ; HOntIQNDiUq2h7O88
+ Lq6
+ ; hB1 YKJgE pnE0a
+
+2187/03/08=1987/05/16 (fVUT) GB0y15 ; gw8ge764c35f
+ [fgY:5j4fG6:uBT] 994884 IuSb
+ [Qv84kw0f1cxt8MBl] -314694 SKN @ uIGy0.488405
+ ; S x865af7EOVbh09z1C:atG
+ C:aOmIU 6quv27:L8:fO0X61IFuzPKm
+ ; cU95Tz:wN9F99u2C:7QW2R6QdK:y:5Lcdf
+
+2187/03/11=1987/05/18 * (Q2P) kOT0:08TY
+ r19iHviTP MQmbBklzoe5Zy:8T4 -701612X @ 1.347401 dhCZ
+ j8hn 8a:zJvx -950080X ; X6V4:Vrz7:A9
+ ChMhD kwW2Drf8oW4 m23b6 rg17K cc
+
+2187/03/16 * (tZ) U C44:BGa4J6Bzwwb4o
+ [YK49QGHo:U167ZuH:Sus] -653997 r @ 990828 WsMH
+ ; YY7Vl4m0y6h:97Eb:t:WZ38
+ [rkd6eQ QnFRO4Eap1:o24ze7 MJta:5Lmw8y1] 713018 dOybc @ 867696 pqosoj
+ L rGB fhmmAj41N:75MlS:HI02Dhtvv92:9
+
+2187/03/19=1987/05/20 * (C) x4MFm08t8:Rv484
+ ; pteIOL8G3L7K:PiF:ed01NaE:5
+ jLXaJ7:TPkx:hnc0a84T949V -337155Pt
+ [z Cimq6yQ5 6Hz:4:y j3pTBDWr:Xwi5xa4fT0] egJUlL927254 @ ETLYp 830216
+ ; i5s0qZi5:it:qv1g 35vrb4GY:4y5
+ (aGO8o973:8:DqP588) cReiuY -813613 @ ZVwoPf 932860
+ [iG0OQ:tWl:Y:F59 R09pKiI] 499724 y @ qwy 1.437329
+ ; bNO myx5K3DhtxI0gZGc4eWCtZ:Nsb:l7Yx 3v
+ [OT2sQn:78mn:6dC6k2BPLg8Xu:1NV8GHg6cq9d] yFpTo -290498 @ PdADxe 2.729485
+ W2C:PzB:a7iA:VHeXq7gYKI vM2611:bCoq aHgK 381854 @ 721958RKv
+ pPYXx2wrFvMC:94zr3C9T1TdhR6D4
+
+2187/03/25 * (R) Z6et66o5F44:HG74D5gdk9
+ ; I8k7lSGq5223eFvFeSX4B20O
+ EiOxe -49170.3ptFX @ WYtmyT 781596
+ [cn U0zGj:Ylm2R:4a Sy] pxLB-155187
+ x:yw8duO9Ic:4CqN:AUa xd
+
+2187/03/27 * (tg) VirzaV9213J8:jkhY7b
+ (Kk:22T6893q129HLfMQ9QZf K66Kc:1 Qu:51Ki) hEP288640 @ 1.734694 ES
+ [yP7cI1x:Ns7Ik:CF 8W:2r:tT8r:ND3K4naIL] vnCq-270931 @ 368422 Qum
+ [OkJ:WvF64D87M22b58xgnAS2yf85] -542640 eM
+ [P U] 602501 oUB
+ c32Ww93:Z:mj7BK
+
+2187/03/28=1987/05/21 ! (kIWM) lz L5
+ (HoA7y0U4v4R458U80K0wqj4V8L:3Hy hK:u2o) baf 692841
+ (tX) -864521 x @ Vy0.360209 ; Wxe043p9:061
+ (Lq:5g7L:wwv:HyHFPCZYy) MYpd631128 @ 508656Cz
+ (x5 79ER 2Z3I0U19 47VfLtNKOq:2X) -696823bSC ; a8:Ad6LdI
+
+2187/03/29=1987/05/24 * (O) E0Rfh34
+ t4FdLx3:l:Ck6m3VJ stAj-908528
+ ; vQ8h:OiGS:f7CG 5 Y7fBz d10
+ z 2936srygkDWhn1c4jyG:L:nHpTrnLB51 vG75178.3
+ ; UfL7dG5a87Mm430vKtQ4Z:M2sdMzh3:a
+ [bdA:M:AM9FCXQm6HMGIB7 Lz:YV4tm3:r:SN] 38780.8HvaL @ HamR 19.0182771
+ ; z4KY C:Q:3h2 X 7
+ (R:n9:lXU) YTx-417744 @ 1.230378 D
+ [DLs 9 mtV 1G:b:Bep yVU n93Hbd:8By2Mx:M] -48707.2 a
+ [R:Goz1E0Bj:blF5Hl] -298794rPVm @ 3.283965 bUoyr
+ ; KYa8M9:6482B650mXUE7b:Ka
+ w8NK7U54q7vHGU0l30t:Il:3P:U T:SfY0
+
+2187/04/01=1987/05/26 ! (Eq) M59Ml:3
+ K ASPeZQ:7LW:wzN2QaUr77OXr wS-848544 @ Exd 0.625834
+ (tX0 1Uhq2Q969Z5x07I4B:8:n2t4T4V:E:6K) rQem -637441 ; ErSB:G0z
+ RqXG2 IZT646tE30:n84Y fEt-767950 @ 0.594623 Hkqq
+ ; pw3k2j 4KT D3Uo:B27e:WKDiuOD43L
+ [C3] BheR-157970
+ (A8p:062sBPYe8e:6oK:n 8X:87Qn) 982770 uVsEo
+ ; oHE U:F7z1f1b8mTv:s 2KwNo7 WgI
+ [D20EU:1] Sppd 837068
+ Bdn0znI799:07:s60 M5099z7
+ ; dEGfxH:U8p6z8DBSZ:diiQ49H21 6
+
+2187/04/04 * (M80a) Z:k206
+ [x7:anc] 437316 Dqk @ eZCzj 0.285032
+ [hC705 NtL:iP:q3608P93d7P:GdE] 544670li
+ ; oy:4zAY3upE31j0VUKCo95b84:O9E5d365E:4
+ ysN:P:56bd43Z:v:krkEyf R y287D
+ ; eZ U0AU4:MSGD:jjK7O94rD3webUWW1:4r0:07
+
+2187/04/07 (vvA) wc05O32W:H34:Y990
+ jBCX1J524A63U1k1j98823 2PYK886n 391730qA
+ tf50 ptOxzto:d6O0ye:cg8MIIR9C3ZlTRQ1 nx920305 @ 1.019439 MyVL
+ (UaTIt08Xl47:98zv83X92k3Ap) nlfkS 154433
+ (j3M44pR2dc4J:rTP7oN 2kO5 GOp:2zo8I) PXO-126823
+ ; yM21414i0eV2HAu50r61:5WN:2ApRhE:sM:ic
+ Xs551d 14OR5:j:5:u
+ ; psjmtc 57 BvF44CTmU7BXYna9w:2e58Wk5dV
+
+2187/04/12 * (Rh2) xe:4694A4vNXtTO:BRdX4n:U:6gLXW4atziLPi
+ h:E31A:6lSbJKE181aNzg2l2s1q -158224QX @ dKAD 4.682267
+ (pfitL560:H:rL2O7L) 976398 wMZ @ t486509
+ Motxoa 3u1 D 58373.9 V @ 3.1142171 a
+ ; tnBH6o 757IL 3:bche8 5 V:6 F29
+ [U 76 7PO6E2M6fJ47pk3no K1KI6r] 690776 cL
+ ; Tz1W zMl:6r0Sr67wwiv6mHI1:UMowDl
+ (A:4s97lX2ZJg5XL:JASmf:H) wTEdPr 126890
+ ; E8N231t1v62wd53wZ3S7ZJ
+ [MkN6f0006:53MX36298W vL2Rr] 131653voz
+ i:Y82PTu8o0RsU5c393 ; m09zvwT873z02
+
+2187/04/16 * (O) g09nmf1f ; fiQ T4D2:E
+ pNwv4w va614303 @ BfEt776882
+ [z 8M3qc:0W6 323:7 HE46vE5goXpC4C] GZatQD349279 ; c79
+ N6Ny7D0NikU2Qzy:W:N4M:94F7D:C zua3Gr ol-473902 @ TiG1.58947
+ ; USUm8 I01T7:rL9xC4H6QaI1fI4zg4iw9D9D94NY
+ iK9PGH2Lr:5xL 11077X ; WiNki
+ QxGAnH:0i1:5:hpK1454yx
+
+2187/04/18=1987/05/27 (d6 76) WKycS8BB4k2pWB6U1 TqC799Q3Q:Q:uvDbP v
+ ; S1 H:53Fz:Z9RY7660oS2:iEzlx8zId1KHlAp13
+ WAIZL7YC8T6xsxb C lEBkQZcC6ZYX8oUdjs aBsqCO-859192 ; X
+ (dVeDho1zLvBM1:bc2907v rw6w:fIyj) rJO-348003 @ 0.5828lNOAP
+ [VYR86aOPCBtU:T43s31qNrcmX55] 148376Kaqj
+ ; Hb5Mz2T33FTGp:6mf92L1
+ g0P FOnuBD634440
+ Eu2590k:6 542890 YbTkPd
+ ; MG7:fX1QN7F:aBWcZ WK:miVS9IS4
+ TXhdCnW:q3 83Q0:A:TLa:P1 389207Qu @ ZxD 474844
+ ; ze Xr:DiUmY4O5a494 E 7C jd9f:y
+ ej:OV1p
+ ; UQIvt cFi75q3l7:33q9V4epmq1c3o:MQY9:4
+
+2187/04/19=1987/05/29 * (yIEGx) vtu yZ:FLNg8 bz81244o 1
+ [eQ0:vQFftKq312 5:qt4OJRF14:8iUS9] -514867H
+ [zS4kj:1U364n 77yT4heLR0WCtP:J:qpTVC] C 626719
+ ; k61HYqVgh4pw4PSJ:8Zd5c0LvKhEqop
+ hQu J5:iL7i:dlczgv5 aUXZ:SW20:d
+ ; B6CQoX:m7:T0DObHKf:c35E tVQg:6N7 XR0yk1F
+
+2187/04/25 (d5) mO3V65tcQ93f:bpH2O4KQc7i8A3ubo64L
+ [cY8j:X:D1g53O] 913440 AkznZ
+ ; qiWp0:1K:9:yoagiids8YU8GazTJnDZyJMuJjU
+ [h 6v3:GS9 8] w 909579.0 @ 0.439321 a
+ QpWryY4
+
+2187/04/26 * (Oa X8v) nTu ; Blnf
+ RcSi7T4:bA87Zk v1a6Bue2RiF3Q:1vHkrC Yd-594954 @ 379530 uXzDxT
+ (jlB2E47ka6U7mwZ3Tp:56wE:w Gr5pco7WO) MJ -210135
+ (HrjMwB92A2:4:bnLz1hf5EAIx8wo71 AnSM83) PzifkG-18466.2 @ 532525.0 a
+ a E913Z48r PEZ930954 @ TWN0.26211
+ K4:3w6:okgb7jHi3He7DMv:h6N:W15Go9 ; OLa p:p6ITR
+
+2187/04/28 ! (eq) I87a 1T 0f95
+ (wD) ZGCAmF-128472
+ ; h6161Ck29nuU0N764bi 4g:0W
+ (Ri:q26Y9xE ubzMbbB672:pM0:QA) 68525.6QBwZl @ 750604 joWS
+
+2187/04/30=1987/06/03 ! (B) tv2:A:T22kI16n5J6mbHh:qZj:E:86
+ (ktL4z m2B5cKS4m53CgD:MnTTq584P8:6) 655291 eOEUll @ 594372OkUXd ; upZep79v
+ (bYT3j0yJy8fIq:2O48R70YV5T34) -498403 RaGA @ 1.611509AfRXi
+ G:2XSwTH3:WI7Y8:H:Kk 134595OIIOE
+ ; p:38 jzL2NZhQjy5fIB0S:ixVU0
+ [BTLZ Y7Kd8W:mo6rR] -142806 ZUSM @ iV629749
+ ; VRFPZ40e:B8vMk8VYpyaxYT T1f1jY8qHg69LxTr
+ (QzQvt5:a) 863612 C
+ ; UW7ldN1R6:JV79EzO9I5nkQKqXNx
+ (K0jG1Nn6xW6qmGoK852Wm82P891w O) w -639451.0
+ ; b2ERs49v6Ri734X01
+ STI0MT
+ ; kpM7x:a6:n61Z1k7 uY4ABsJ93
+
+2187/05/06=1987/06/07 ! (DWS3) G Z r2r iYLKfxR7:vrl9vr707P6pb 94XSd
+ HC5FR0S vxXRGK -142673 @ xAV 605535
+ [Fy1:u15syG 8:8C 38vB:178ExtQk5eBMq7F:blU] -130770oz
+ QvJZ:t xw:N
+
+2187/05/09 * (nKVz6) a9:T7
+ ; eT75RyW4Xd8a f1a679UnNi SH065V KnOo9
+ l7liL:4Qnz07kFUQ 800903 emTA @ 976479MTcm
+ (a:d) -761443Ay @ 0.576885 TDa
+ i
+
+2187/05/12=1987/06/09 ! (G3CN) nm r5
+ (rsiBbx8T EXY5) 386928 flTii @ 2.000225 DE
+ HQg3:FK1EgO -941250jElq ; Yn6gjO
+ C42Y z:mOpuX:f:nnk:tx
+
+2187/05/13 * (r6e y0) V65by ; Z X8Whns
+ [h96nQFF32fyO8y] 968994 UBNDg
+ ; T72YEmnsvcmFX91DLNMg w2948464
+ [Qwk40WBS0:N2V WUW:BM7M4:09961G0] 130897QkeP @ 719156 E
+ l5C402g:8ym9I0T1id zl7:sa811F1q vbUv:8Q
+ ; t5AnGg88R45W:S161kRC0o
+>>>2
+=== 0
diff --git a/test/baseline/opt-sort-all.test b/test/baseline/opt-sort-all.test
new file mode 100644
index 00000000..b289f8e8
--- /dev/null
+++ b/test/baseline/opt-sort-all.test
@@ -0,0 +1,122 @@
+reg --monthly --sort=-amount
+<<<
+2008/01/11 LIAT
+ Expenses:Travel:Airfare $40.00
+ Liabilities:MasterCard
+
+2008/01/14 cheaptickets.com
+ Expenses:Travel:Airfare $182.19
+ Liabilities:MasterCard
+
+2008/02/05 CTX
+ Expenses:Travel:Auto $240.38
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/22 BUDGET RENT-A-CAR
+ Expenses:Travel:Auto $40.59
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/08/08 BCIS I-131 FILING FEE-
+ Expenses:Travel:Passport $170.00
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/22 AGNT FEE
+ Expenses:Travel:Airfare $70.00
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 LIAT 1974 LIMITED
+ Expenses:Travel:Airfare $418.34
+ Liabilities:MasterCard
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+>>>1
+08-Jan-01 - 08-Jan-31 Ex:Travel:Airfare $222.19 $222.19
+ Liabilities:MasterCard $-222.19 0
+08-Feb-01 - 08-Feb-29 Ex:Travel:Airfare $477.60 $477.60
+ Expenses:Travel:Auto $280.97 $758.57
+ Liabilities:MasterCard $-758.57 0
+08-Mar-01 - 08-Mar-31 Ex:Travel:Airfare $2,463.20 $2,463.20
+ Liabilities:MasterCard $-2,463.20 0
+08-Apr-01 - 08-Apr-30 Ex:Travel:Airfare $1,186.14 $1,186.14
+ Liabilities:MasterCard $-1,186.14 0
+08-Aug-01 - 08-Aug-31 Ex:Travel:Passport $170.00 $170.00
+ Liabilities:MasterCard $-170.00 0
+08-Sep-01 - 08-Sep-30 Ex:Travel:Airfare $3,925.94 $3,925.94
+ Liabilities:MasterCard $-3,925.94 0
+08-Dec-01 - 08-Dec-31 Ex:Travel:Passport $254.00 $254.00
+ Assets:Checking $-254.00 0
+>>>2
+=== 0
+reg --monthly --sort-all=-amount
+>>>1
+08-Sep-01 - 08-Sep-30 Ex:Travel:Airfare $3,925.94 $3,925.94
+08-Mar-01 - 08-Mar-31 Ex:Travel:Airfare $2,463.20 $6,389.14
+08-Apr-01 - 08-Apr-30 Ex:Travel:Airfare $1,186.14 $7,575.28
+08-Feb-01 - 08-Feb-29 Ex:Travel:Airfare $477.60 $8,052.88
+ Expenses:Travel:Auto $280.97 $8,333.85
+08-Dec-01 - 08-Dec-31 Ex:Travel:Passport $254.00 $8,587.85
+08-Jan-01 - 08-Jan-31 Ex:Travel:Airfare $222.19 $8,810.04
+08-Aug-01 - 08-Aug-31 Ex:Travel:Passport $170.00 $8,980.04
+ Liabilities:MasterCard $-170.00 $8,810.04
+08-Jan-01 - 08-Jan-31 Liabilities:MasterCard $-222.19 $8,587.85
+08-Dec-01 - 08-Dec-31 Assets:Checking $-254.00 $8,333.85
+08-Feb-01 - 08-Feb-29 Liabilities:MasterCard $-758.57 $7,575.28
+08-Apr-01 - 08-Apr-30 Liabilities:MasterCard $-1,186.14 $6,389.14
+08-Mar-01 - 08-Mar-31 Liabilities:MasterCard $-2,463.20 $3,925.94
+08-Sep-01 - 08-Sep-30 Liabilities:MasterCard $-3,925.94 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-sort-xacts.test b/test/baseline/opt-sort-xacts.test
new file mode 100644
index 00000000..4882e18f
--- /dev/null
+++ b/test/baseline/opt-sort-xacts.test
@@ -0,0 +1,176 @@
+reg --sort=account
+<<<
+2008/01/11 LIAT
+ Expenses:Travel:Airfare $40.00
+ Liabilities:MasterCard
+
+2008/01/14 cheaptickets.com
+ Expenses:Travel:Airfare $182.19
+ Liabilities:MasterCard
+
+2008/02/05 CTX
+ Expenses:Travel:Auto $240.38
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/22 BUDGET RENT-A-CAR
+ Expenses:Travel:Auto $40.59
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/08/08 BCIS I-131 FILING FEE-
+ Expenses:Travel:Passport $170.00
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/22 AGNT FEE
+ Expenses:Travel:Airfare $70.00
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 LIAT 1974 LIMITED
+ Expenses:Travel:Airfare $418.34
+ Liabilities:MasterCard
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+>>>1
+08-Dec-26 U.S. Department of .. Assets:Checking $-127.00 $-127.00
+08-Dec-26 U.S. Department of .. Assets:Checking $-127.00 $-254.00
+08-Jan-11 LIAT Ex:Travel:Airfare $40.00 $-214.00
+08-Jan-14 cheaptickets.com Ex:Travel:Airfare $182.19 $-31.81
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $206.99
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $445.79
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $1,677.39
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $2,908.99
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $3,064.85
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $3,220.71
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $3,657.92
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $4,095.13
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $5,007.73
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $5,920.33
+08-Sep-22 AGNT FEE Ex:Travel:Airfare $70.00 $5,990.33
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $6,796.53
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $7,602.73
+08-Sep-22 LIAT 1974 LIMITED Ex:Travel:Airfare $418.34 $8,021.07
+08-Feb-05 CTX Expenses:Travel:Auto $240.38 $8,261.45
+08-Feb-22 BUDGET RENT-A-CAR Expenses:Travel:Auto $40.59 $8,302.04
+08-Aug-08 BCIS I-131 FILING F.. Ex:Travel:Passport $170.00 $8,472.04
+08-Dec-26 U.S. Department of .. Ex:Travel:Passport $127.00 $8,599.04
+08-Dec-26 U.S. Department of .. Ex:Travel:Passport $127.00 $8,726.04
+08-Jan-11 LIAT Liabilities:MasterCard $-40.00 $8,686.04
+08-Jan-14 cheaptickets.com Liabilities:MasterCard $-182.19 $8,503.85
+08-Feb-05 CTX Liabilities:MasterCard $-240.38 $8,263.47
+08-Feb-05 UNITED Liabilities:MasterCard $-238.80 $8,024.67
+08-Feb-05 UNITED Liabilities:MasterCard $-238.80 $7,785.87
+08-Feb-22 BUDGET RENT-A-CAR Liabilities:MasterCard $-40.59 $7,745.28
+08-Mar-16 IBERIA Liabilities:MasterCard $-1,231.60 $6,513.68
+08-Mar-16 IBERIA Liabilities:MasterCard $-1,231.60 $5,282.08
+08-Apr-03 AMERICAN Liabilities:MasterCard $-155.86 $5,126.22
+08-Apr-03 AMERICAN Liabilities:MasterCard $-155.86 $4,970.36
+08-Apr-30 UNITED Liabilities:MasterCard $-437.21 $4,533.15
+08-Apr-30 UNITED Liabilities:MasterCard $-437.21 $4,095.94
+08-Aug-08 BCIS I-131 FILING F.. Liabilities:MasterCard $-170.00 $3,925.94
+08-Sep-06 AMERICAN Liabilities:MasterCard $-912.60 $3,013.34
+08-Sep-06 AMERICAN Liabilities:MasterCard $-912.60 $2,100.74
+08-Sep-22 AGNT FEE Liabilities:MasterCard $-70.00 $2,030.74
+08-Sep-22 DELTA Liabilities:MasterCard $-806.20 $1,224.54
+08-Sep-22 DELTA Liabilities:MasterCard $-806.20 $418.34
+08-Sep-22 LIAT 1974 LIMITED Liabilities:MasterCard $-418.34 0
+>>>2
+=== 0
+reg --sort-xacts=account
+>>>1
+08-Jan-11 LIAT Ex:Travel:Airfare $40.00 $40.00
+ Liabilities:MasterCard $-40.00 0
+08-Jan-14 cheaptickets.com Ex:Travel:Airfare $182.19 $182.19
+ Liabilities:MasterCard $-182.19 0
+08-Feb-05 CTX Expenses:Travel:Auto $240.38 $240.38
+ Liabilities:MasterCard $-240.38 0
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $238.80
+ Liabilities:MasterCard $-238.80 0
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $238.80
+ Liabilities:MasterCard $-238.80 0
+08-Feb-22 BUDGET RENT-A-CAR Expenses:Travel:Auto $40.59 $40.59
+ Liabilities:MasterCard $-40.59 0
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $1,231.60
+ Liabilities:MasterCard $-1,231.60 0
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $1,231.60
+ Liabilities:MasterCard $-1,231.60 0
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $155.86
+ Liabilities:MasterCard $-155.86 0
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $155.86
+ Liabilities:MasterCard $-155.86 0
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $437.21
+ Liabilities:MasterCard $-437.21 0
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $437.21
+ Liabilities:MasterCard $-437.21 0
+08-Aug-08 BCIS I-131 FILING F.. Ex:Travel:Passport $170.00 $170.00
+ Liabilities:MasterCard $-170.00 0
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $912.60
+ Liabilities:MasterCard $-912.60 0
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $912.60
+ Liabilities:MasterCard $-912.60 0
+08-Sep-22 AGNT FEE Ex:Travel:Airfare $70.00 $70.00
+ Liabilities:MasterCard $-70.00 0
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $806.20
+ Liabilities:MasterCard $-806.20 0
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $806.20
+ Liabilities:MasterCard $-806.20 0
+08-Sep-22 LIAT 1974 LIMITED Ex:Travel:Airfare $418.34 $418.34
+ Liabilities:MasterCard $-418.34 0
+08-Dec-26 U.S. Department of .. Assets:Checking $-127.00 $-127.00
+ Ex:Travel:Passport $127.00 0
+08-Dec-26 U.S. Department of .. Assets:Checking $-127.00 $-127.00
+ Ex:Travel:Passport $127.00 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-sort.test b/test/baseline/opt-sort.test
new file mode 100644
index 00000000..27efe31b
--- /dev/null
+++ b/test/baseline/opt-sort.test
@@ -0,0 +1,246 @@
+reg airfare --sort=date
+<<<
+2008/01/11 LIAT
+ Expenses:Travel:Airfare $40.00
+ Liabilities:MasterCard
+
+2008/01/14 cheaptickets.com
+ Expenses:Travel:Airfare $182.19
+ Liabilities:MasterCard
+
+2008/02/05 CTX
+ Expenses:Travel:Auto $240.38
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/22 BUDGET RENT-A-CAR
+ Expenses:Travel:Auto $40.59
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/08/08 BCIS I-131 FILING FEE-
+ Expenses:Travel:Passport $170.00
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/22 AGNT FEE
+ Expenses:Travel:Airfare $70.00
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 LIAT 1974 LIMITED
+ Expenses:Travel:Airfare $418.34
+ Liabilities:MasterCard
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+>>>1
+08-Jan-11 LIAT Ex:Travel:Airfare $40.00 $40.00
+08-Jan-14 cheaptickets.com Ex:Travel:Airfare $182.19 $222.19
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $460.99
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $699.79
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $1,931.39
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $3,162.99
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $3,318.85
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $3,474.71
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $3,911.92
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $4,349.13
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $5,261.73
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $6,174.33
+08-Sep-22 AGNT FEE Ex:Travel:Airfare $70.00 $6,244.33
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $7,050.53
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $7,856.73
+08-Sep-22 LIAT 1974 LIMITED Ex:Travel:Airfare $418.34 $8,275.07
+>>>2
+=== 0
+reg airfare --sort=date,amount
+>>>1
+08-Jan-11 LIAT Ex:Travel:Airfare $40.00 $40.00
+08-Jan-14 cheaptickets.com Ex:Travel:Airfare $182.19 $222.19
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $460.99
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $699.79
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $1,931.39
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $3,162.99
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $3,318.85
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $3,474.71
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $3,911.92
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $4,349.13
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $5,261.73
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $6,174.33
+08-Sep-22 AGNT FEE Ex:Travel:Airfare $70.00 $6,244.33
+08-Sep-22 LIAT 1974 LIMITED Ex:Travel:Airfare $418.34 $6,662.67
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $7,468.87
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $8,275.07
+>>>2
+=== 0
+reg airfare --sort=date,-amount
+>>>1
+08-Jan-11 LIAT Ex:Travel:Airfare $40.00 $40.00
+08-Jan-14 cheaptickets.com Ex:Travel:Airfare $182.19 $222.19
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $460.99
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $699.79
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $1,931.39
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $3,162.99
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $3,318.85
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $3,474.71
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $3,911.92
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $4,349.13
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $5,261.73
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $6,174.33
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $6,980.53
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $7,786.73
+08-Sep-22 LIAT 1974 LIMITED Ex:Travel:Airfare $418.34 $8,205.07
+08-Sep-22 AGNT FEE Ex:Travel:Airfare $70.00 $8,275.07
+>>>2
+=== 0
+reg airfare --sort=-date,-amount
+>>>1
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $806.20
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $1,612.40
+08-Sep-22 LIAT 1974 LIMITED Ex:Travel:Airfare $418.34 $2,030.74
+08-Sep-22 AGNT FEE Ex:Travel:Airfare $70.00 $2,100.74
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $3,013.34
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $3,925.94
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $4,363.15
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $4,800.36
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $4,956.22
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $5,112.08
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $6,343.68
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $7,575.28
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $7,814.08
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $8,052.88
+08-Jan-14 cheaptickets.com Ex:Travel:Airfare $182.19 $8,235.07
+08-Jan-11 LIAT Ex:Travel:Airfare $40.00 $8,275.07
+>>>2
+=== 0
+bal --sort=total
+>>>1
+ $-8,726.04 Liabilities:MasterCard
+ $-254.00 Assets:Checking
+ $8,980.04 Expenses:Travel
+ $280.97 Auto
+ $424.00 Passport
+ $8,275.07 Airfare
+--------------------
+ 0
+>>>2
+=== 0
+bal --sort=-total
+>>>1
+ $8,980.04 Expenses:Travel
+ $8,275.07 Airfare
+ $424.00 Passport
+ $280.97 Auto
+ $-254.00 Assets:Checking
+ $-8,726.04 Liabilities:MasterCard
+--------------------
+ 0
+>>>2
+=== 0
+bal --sort=-account
+>>>1
+ $-8,726.04 Liabilities:MasterCard
+ $8,980.04 Expenses:Travel
+ $424.00 Passport
+ $280.97 Auto
+ $8,275.07 Airfare
+ $-254.00 Assets:Checking
+--------------------
+ 0
+>>>2
+=== 0
+reg --sort=account
+>>>1
+08-Dec-26 U.S. Department of .. Assets:Checking $-127.00 $-127.00
+08-Dec-26 U.S. Department of .. Assets:Checking $-127.00 $-254.00
+08-Jan-11 LIAT Ex:Travel:Airfare $40.00 $-214.00
+08-Jan-14 cheaptickets.com Ex:Travel:Airfare $182.19 $-31.81
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $206.99
+08-Feb-05 UNITED Ex:Travel:Airfare $238.80 $445.79
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $1,677.39
+08-Mar-16 IBERIA Ex:Travel:Airfare $1,231.60 $2,908.99
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $3,064.85
+08-Apr-03 AMERICAN Ex:Travel:Airfare $155.86 $3,220.71
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $3,657.92
+08-Apr-30 UNITED Ex:Travel:Airfare $437.21 $4,095.13
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $5,007.73
+08-Sep-06 AMERICAN Ex:Travel:Airfare $912.60 $5,920.33
+08-Sep-22 AGNT FEE Ex:Travel:Airfare $70.00 $5,990.33
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $6,796.53
+08-Sep-22 DELTA Ex:Travel:Airfare $806.20 $7,602.73
+08-Sep-22 LIAT 1974 LIMITED Ex:Travel:Airfare $418.34 $8,021.07
+08-Feb-05 CTX Expenses:Travel:Auto $240.38 $8,261.45
+08-Feb-22 BUDGET RENT-A-CAR Expenses:Travel:Auto $40.59 $8,302.04
+08-Aug-08 BCIS I-131 FILING F.. Ex:Travel:Passport $170.00 $8,472.04
+08-Dec-26 U.S. Department of .. Ex:Travel:Passport $127.00 $8,599.04
+08-Dec-26 U.S. Department of .. Ex:Travel:Passport $127.00 $8,726.04
+08-Jan-11 LIAT Liabilities:MasterCard $-40.00 $8,686.04
+08-Jan-14 cheaptickets.com Liabilities:MasterCard $-182.19 $8,503.85
+08-Feb-05 CTX Liabilities:MasterCard $-240.38 $8,263.47
+08-Feb-05 UNITED Liabilities:MasterCard $-238.80 $8,024.67
+08-Feb-05 UNITED Liabilities:MasterCard $-238.80 $7,785.87
+08-Feb-22 BUDGET RENT-A-CAR Liabilities:MasterCard $-40.59 $7,745.28
+08-Mar-16 IBERIA Liabilities:MasterCard $-1,231.60 $6,513.68
+08-Mar-16 IBERIA Liabilities:MasterCard $-1,231.60 $5,282.08
+08-Apr-03 AMERICAN Liabilities:MasterCard $-155.86 $5,126.22
+08-Apr-03 AMERICAN Liabilities:MasterCard $-155.86 $4,970.36
+08-Apr-30 UNITED Liabilities:MasterCard $-437.21 $4,533.15
+08-Apr-30 UNITED Liabilities:MasterCard $-437.21 $4,095.94
+08-Aug-08 BCIS I-131 FILING F.. Liabilities:MasterCard $-170.00 $3,925.94
+08-Sep-06 AMERICAN Liabilities:MasterCard $-912.60 $3,013.34
+08-Sep-06 AMERICAN Liabilities:MasterCard $-912.60 $2,100.74
+08-Sep-22 AGNT FEE Liabilities:MasterCard $-70.00 $2,030.74
+08-Sep-22 DELTA Liabilities:MasterCard $-806.20 $1,224.54
+08-Sep-22 DELTA Liabilities:MasterCard $-806.20 $418.34
+08-Sep-22 LIAT 1974 LIMITED Liabilities:MasterCard $-418.34 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-start-of-week.test b/test/baseline/opt-start-of-week.test
new file mode 100644
index 00000000..04fae951
--- /dev/null
+++ b/test/baseline/opt-start-of-week.test
@@ -0,0 +1,224 @@
+reg --weekly --start-of-week=mon books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+07-Dec-31 - 08-Jan-06 Expenses:Books $10.00 $10.00
+08-Jan-28 - 08-Feb-03 Expenses:Books $30.00 $40.00
+08-Feb-25 - 08-Mar-02 Expenses:Books $50.00 $90.00
+08-Mar-31 - 08-Apr-06 Expenses:Books $70.00 $160.00
+08-Apr-28 - 08-May-04 Expenses:Books $90.00 $250.00
+08-May-26 - 08-Jun-01 Expenses:Books $110.00 $360.00
+08-Jun-30 - 08-Jul-06 Expenses:Books $130.00 $490.00
+08-Jul-28 - 08-Aug-03 Expenses:Books $150.00 $640.00
+08-Aug-25 - 08-Aug-31 Expenses:Books $80.00 $720.00
+08-Sep-01 - 08-Sep-07 Expenses:Books $90.00 $810.00
+08-Sep-29 - 08-Oct-05 Expenses:Books $190.00 $1000.00
+08-Oct-27 - 08-Nov-02 Expenses:Books $210.00 $1210.00
+08-Nov-24 - 08-Nov-30 Expenses:Books $110.00 $1320.00
+08-Dec-01 - 08-Dec-07 Expenses:Books $120.00 $1440.00
+08-Dec-29 - 09-Jan-04 Expenses:Books $130.00 $1570.00
+09-Jan-26 - 09-Feb-01 Expenses:Books $30.00 $1600.00
+09-Feb-23 - 09-Mar-01 Expenses:Books $50.00 $1650.00
+09-Mar-30 - 09-Apr-05 Expenses:Books $70.00 $1720.00
+09-Apr-27 - 09-May-03 Expenses:Books $90.00 $1810.00
+09-May-25 - 09-May-31 Expenses:Books $50.00 $1860.00
+09-Jun-01 - 09-Jun-07 Expenses:Books $60.00 $1920.00
+09-Jun-29 - 09-Jul-05 Expenses:Books $130.00 $2050.00
+09-Jul-27 - 09-Aug-02 Expenses:Books $150.00 $2200.00
+09-Aug-31 - 09-Sep-06 Expenses:Books $170.00 $2370.00
+09-Sep-28 - 09-Oct-04 Expenses:Books $190.00 $2560.00
+09-Oct-26 - 09-Nov-01 Expenses:Books $210.00 $2770.00
+09-Nov-30 - 09-Dec-06 Expenses:Books $230.00 $3000.00
+09-Dec-28 - 10-Jan-03 Expenses:Books $120.00 $3120.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-strict.test b/test/baseline/opt-strict.test
new file mode 100644
index 00000000..1917d946
--- /dev/null
+++ b/test/baseline/opt-strict.test
@@ -0,0 +1,23 @@
+reg --strict
+<<<
+2007/02/02 * Foo
+ Expenses:Food $10.00
+ Assets:Cash
+
+2007/02/03 Bar
+ * Expenses:Food $20.00
+ Assets:Cash
+
+2007/02/02 Baz
+ Expenses:Foodx $30.00
+ Assets:Cash
+>>>1
+07-Feb-02 Foo Expenses:Food $10.00 $10.00
+ Assets:Cash $-10.00 0
+07-Feb-02 Baz Expenses:Foodx $30.00 $30.00
+ Assets:Cash $-30.00 0
+07-Feb-03 Bar Expenses:Food $20.00 $20.00
+ Assets:Cash $-20.00 0
+>>>2
+Warning: "$FILE", line 10: Unknown account 'Expenses:Foodx'
+=== 0
diff --git a/test/baseline/opt-subtotal.test b/test/baseline/opt-subtotal.test
new file mode 100644
index 00000000..41defbc1
--- /dev/null
+++ b/test/baseline/opt-subtotal.test
@@ -0,0 +1,93 @@
+reg --subtotal
+<<<
+2008/01/11 LIAT
+ Expenses:Travel:Airfare $40.00
+ Liabilities:MasterCard
+
+2008/01/14 cheaptickets.com
+ Expenses:Travel:Airfare $182.19
+ Liabilities:MasterCard
+
+2008/02/05 CTX
+ Expenses:Travel:Auto $240.38
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/22 BUDGET RENT-A-CAR
+ Expenses:Travel:Auto $40.59
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/08/08 BCIS I-131 FILING FEE-
+ Expenses:Travel:Passport $170.00
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/22 AGNT FEE
+ Expenses:Travel:Airfare $70.00
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 LIAT 1974 LIMITED
+ Expenses:Travel:Airfare $418.34
+ Liabilities:MasterCard
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+>>>1
+08-Jan-11 - 08-Dec-26 Assets:Checking $-254.00 $-254.00
+ Ex:Travel:Airfare $8,275.07 $8,021.07
+ Expenses:Travel:Auto $280.97 $8,302.04
+ Ex:Travel:Passport $424.00 $8,726.04
+ Liabilities:MasterCard $-8,726.04 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-tail.test b/test/baseline/opt-tail.test
new file mode 100644
index 00000000..0f0b862b
--- /dev/null
+++ b/test/baseline/opt-tail.test
@@ -0,0 +1,206 @@
+reg --tail=10 books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+09-Aug-01 August Expenses:Books $80.00 $2200.00
+09-Aug-31 End of August Expenses:Books $80.00 $2280.00
+09-Sep-01 September Expenses:Books $90.00 $2370.00
+09-Sep-30 End of September Expenses:Books $90.00 $2460.00
+09-Oct-01 October Expenses:Books $100.00 $2560.00
+09-Oct-31 End of October Expenses:Books $100.00 $2660.00
+09-Nov-01 November Expenses:Books $110.00 $2770.00
+09-Nov-30 End of November Expenses:Books $110.00 $2880.00
+09-Dec-01 December Expenses:Books $120.00 $3000.00
+09-Dec-31 End of December Expenses:Books $120.00 $3120.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-total-data.test b/test/baseline/opt-total-data.test
new file mode 100644
index 00000000..f1ab33c1
--- /dev/null
+++ b/test/baseline/opt-total-data.test
@@ -0,0 +1,10 @@
+reg --market --total-data
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+2007-02-02 0.35
+2007-02-02 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-total-width.test b/test/baseline/opt-total-width.test
new file mode 100644
index 00000000..1d7b8b94
--- /dev/null
+++ b/test/baseline/opt-total-width.test
@@ -0,0 +1,11 @@
+reg --total-width=25
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ In:Di:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-total.test b/test/baseline/opt-total.test
new file mode 100644
index 00000000..8f4719d2
--- /dev/null
+++ b/test/baseline/opt-total.test
@@ -0,0 +1,10 @@
+reg --total=10
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 10
+ In:Di:Vanguard:VMMXX $-0.35 10
+>>>2
+=== 0
diff --git a/test/baseline/opt-truncate.test b/test/baseline/opt-truncate.test
new file mode 100644
index 00000000..0f9190c2
--- /dev/null
+++ b/test/baseline/opt-truncate.test
@@ -0,0 +1,144 @@
+reg airfare --truncate=leading
+<<<
+2008/01/11 LIAT
+ Expenses:Travel:Airfare $40.00
+ Liabilities:MasterCard
+
+2008/01/14 cheaptickets.com
+ Expenses:Travel:Airfare $182.19
+ Liabilities:MasterCard
+
+2008/02/05 CTX
+ Expenses:Travel:Auto $240.38
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/22 BUDGET RENT-A-CAR
+ Expenses:Travel:Auto $40.59
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/08/08 BCIS I-131 FILING FEE-
+ Expenses:Travel:Passport $170.00
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/22 AGNT FEE
+ Expenses:Travel:Airfare $70.00
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 LIAT 1974 LIMITED
+ Expenses:Travel:Airfare $418.34
+ Liabilities:MasterCard
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+>>>1
+08-Jan-11 LIAT ..enses:Travel:Airfare $40.00 $40.00
+08-Jan-14 cheaptickets.com ..enses:Travel:Airfare $182.19 $222.19
+08-Feb-05 UNITED ..enses:Travel:Airfare $238.80 $460.99
+08-Feb-05 UNITED ..enses:Travel:Airfare $238.80 $699.79
+08-Mar-16 IBERIA ..enses:Travel:Airfare $1,231.60 $1,931.39
+08-Mar-16 IBERIA ..enses:Travel:Airfare $1,231.60 $3,162.99
+08-Apr-03 AMERICAN ..enses:Travel:Airfare $155.86 $3,318.85
+08-Apr-03 AMERICAN ..enses:Travel:Airfare $155.86 $3,474.71
+08-Apr-30 UNITED ..enses:Travel:Airfare $437.21 $3,911.92
+08-Apr-30 UNITED ..enses:Travel:Airfare $437.21 $4,349.13
+08-Sep-06 AMERICAN ..enses:Travel:Airfare $912.60 $5,261.73
+08-Sep-06 AMERICAN ..enses:Travel:Airfare $912.60 $6,174.33
+08-Sep-22 AGNT FEE ..enses:Travel:Airfare $70.00 $6,244.33
+08-Sep-22 DELTA ..enses:Travel:Airfare $806.20 $7,050.53
+08-Sep-22 DELTA ..enses:Travel:Airfare $806.20 $7,856.73
+08-Sep-22 LIAT 1974 LIMITED ..enses:Travel:Airfare $418.34 $8,275.07
+>>>2
+=== 0
+reg airfare --truncate=middle
+>>>1
+08-Jan-11 LIAT Expenses:T..el:Airfare $40.00 $40.00
+08-Jan-14 cheaptickets.com Expenses:T..el:Airfare $182.19 $222.19
+08-Feb-05 UNITED Expenses:T..el:Airfare $238.80 $460.99
+08-Feb-05 UNITED Expenses:T..el:Airfare $238.80 $699.79
+08-Mar-16 IBERIA Expenses:T..el:Airfare $1,231.60 $1,931.39
+08-Mar-16 IBERIA Expenses:T..el:Airfare $1,231.60 $3,162.99
+08-Apr-03 AMERICAN Expenses:T..el:Airfare $155.86 $3,318.85
+08-Apr-03 AMERICAN Expenses:T..el:Airfare $155.86 $3,474.71
+08-Apr-30 UNITED Expenses:T..el:Airfare $437.21 $3,911.92
+08-Apr-30 UNITED Expenses:T..el:Airfare $437.21 $4,349.13
+08-Sep-06 AMERICAN Expenses:T..el:Airfare $912.60 $5,261.73
+08-Sep-06 AMERICAN Expenses:T..el:Airfare $912.60 $6,174.33
+08-Sep-22 AGNT FEE Expenses:T..el:Airfare $70.00 $6,244.33
+08-Sep-22 DELTA Expenses:T..el:Airfare $806.20 $7,050.53
+08-Sep-22 DELTA Expenses:T..el:Airfare $806.20 $7,856.73
+08-Sep-22 LIAT 1974 LIMITED Expenses:T..el:Airfare $418.34 $8,275.07
+>>>2
+=== 0
+reg airfare --truncate=trailing
+>>>1
+08-Jan-11 LIAT Expenses:Travel:Airf.. $40.00 $40.00
+08-Jan-14 cheaptickets.com Expenses:Travel:Airf.. $182.19 $222.19
+08-Feb-05 UNITED Expenses:Travel:Airf.. $238.80 $460.99
+08-Feb-05 UNITED Expenses:Travel:Airf.. $238.80 $699.79
+08-Mar-16 IBERIA Expenses:Travel:Airf.. $1,231.60 $1,931.39
+08-Mar-16 IBERIA Expenses:Travel:Airf.. $1,231.60 $3,162.99
+08-Apr-03 AMERICAN Expenses:Travel:Airf.. $155.86 $3,318.85
+08-Apr-03 AMERICAN Expenses:Travel:Airf.. $155.86 $3,474.71
+08-Apr-30 UNITED Expenses:Travel:Airf.. $437.21 $3,911.92
+08-Apr-30 UNITED Expenses:Travel:Airf.. $437.21 $4,349.13
+08-Sep-06 AMERICAN Expenses:Travel:Airf.. $912.60 $5,261.73
+08-Sep-06 AMERICAN Expenses:Travel:Airf.. $912.60 $6,174.33
+08-Sep-22 AGNT FEE Expenses:Travel:Airf.. $70.00 $6,244.33
+08-Sep-22 DELTA Expenses:Travel:Airf.. $806.20 $7,050.53
+08-Sep-22 DELTA Expenses:Travel:Airf.. $806.20 $7,856.73
+08-Sep-22 LIAT 1974 LIMITED Expenses:Travel:Airf.. $418.34 $8,275.07
+>>>2
+=== 0
diff --git a/test/baseline/opt-unbudgeted.test b/test/baseline/opt-unbudgeted.test
new file mode 100644
index 00000000..e8acee1e
--- /dev/null
+++ b/test/baseline/opt-unbudgeted.test
@@ -0,0 +1,296 @@
+reg --unbudgeted
+<<<
+~ monthly
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/01 January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Liabilities:Cards $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Liabilities:Cards $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Liabilities:Cards $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Liabilities:Cards $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Liabilities:Cards $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Liabilities:Cards $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Liabilities:Cards $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Liabilities:Cards $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Liabilities:Cards $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Liabilities:Cards $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Liabilities:Cards $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Liabilities:Cards $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 January Liabilities:Cards $10.00 $10.00
+08-Jan-31 End of January Liabilities:Cards $10.00 $20.00
+08-Feb-01 February Liabilities:Cards $20.00 $40.00
+08-Feb-28 End of February Liabilities:Cards $20.00 $60.00
+08-Mar-01 March Liabilities:Cards $30.00 $90.00
+08-Mar-31 End of March Liabilities:Cards $30.00 $120.00
+08-Apr-01 April Liabilities:Cards $40.00 $160.00
+08-Apr-30 End of April Liabilities:Cards $40.00 $200.00
+08-May-01 May Liabilities:Cards $50.00 $250.00
+08-May-31 End of May Liabilities:Cards $50.00 $300.00
+08-Jun-01 June Liabilities:Cards $60.00 $360.00
+08-Jun-30 End of June Liabilities:Cards $60.00 $420.00
+08-Jul-01 July Liabilities:Cards $70.00 $490.00
+08-Jul-31 End of July Liabilities:Cards $70.00 $560.00
+08-Aug-01 August Liabilities:Cards $80.00 $640.00
+08-Aug-31 End of August Liabilities:Cards $80.00 $720.00
+08-Sep-01 September Liabilities:Cards $90.00 $810.00
+08-Sep-30 End of September Liabilities:Cards $90.00 $900.00
+08-Oct-01 October Liabilities:Cards $100.00 $1000.00
+08-Oct-31 End of October Liabilities:Cards $100.00 $1100.00
+08-Nov-01 November Liabilities:Cards $110.00 $1210.00
+08-Nov-30 End of November Liabilities:Cards $110.00 $1320.00
+08-Dec-01 December Liabilities:Cards $120.00 $1440.00
+08-Dec-31 End of December Liabilities:Cards $120.00 $1560.00
+09-Jan-01 January Liabilities:Cards $10.00 $1570.00
+09-Jan-31 End of January Liabilities:Cards $10.00 $1580.00
+09-Feb-01 February Liabilities:Cards $20.00 $1600.00
+09-Feb-28 End of February Liabilities:Cards $20.00 $1620.00
+09-Mar-01 March Liabilities:Cards $30.00 $1650.00
+09-Mar-31 End of March Liabilities:Cards $30.00 $1680.00
+09-Apr-01 April Liabilities:Cards $40.00 $1720.00
+09-Apr-30 End of April Liabilities:Cards $40.00 $1760.00
+09-May-01 May Liabilities:Cards $50.00 $1810.00
+09-May-31 End of May Liabilities:Cards $50.00 $1860.00
+09-Jun-01 June Liabilities:Cards $60.00 $1920.00
+09-Jun-30 End of June Liabilities:Cards $60.00 $1980.00
+09-Jul-01 July Liabilities:Cards $70.00 $2050.00
+09-Jul-31 End of July Liabilities:Cards $70.00 $2120.00
+09-Aug-01 August Liabilities:Cards $80.00 $2200.00
+09-Aug-31 End of August Liabilities:Cards $80.00 $2280.00
+09-Sep-01 September Liabilities:Cards $90.00 $2370.00
+09-Sep-30 End of September Liabilities:Cards $90.00 $2460.00
+09-Oct-01 October Liabilities:Cards $100.00 $2560.00
+09-Oct-31 End of October Liabilities:Cards $100.00 $2660.00
+09-Nov-01 November Liabilities:Cards $110.00 $2770.00
+09-Nov-30 End of November Liabilities:Cards $110.00 $2880.00
+09-Dec-01 December Liabilities:Cards $120.00 $3000.00
+09-Dec-31 End of December Liabilities:Cards $120.00 $3120.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-uncleared.test b/test/baseline/opt-uncleared.test
new file mode 100644
index 00000000..95e976ad
--- /dev/null
+++ b/test/baseline/opt-uncleared.test
@@ -0,0 +1,286 @@
+reg --uncleared
+<<<
+2008/01/01 * January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 ! February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 * March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ * Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ * Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ ! Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ ! Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-31 End of January Expenses:Books $10.00 $10.00
+ Assets:Cash $-10.00 0
+08-Feb-01 February Expenses:Books $20.00 $20.00
+ Assets:Cash $-20.00 0
+08-Feb-28 End of February Expenses:Books $20.00 $20.00
+ Assets:Cash $-20.00 0
+08-Mar-31 End of March Expenses:Books $30.00 $30.00
+ Assets:Cash $-30.00 0
+08-Apr-01 April Assets:Cash $-40.00 $-40.00
+08-Apr-30 End of April Assets:Cash $-40.00 $-80.00
+08-May-01 May Expenses:Books $50.00 $-30.00
+ Assets:Cash $-50.00 $-80.00
+08-May-31 End of May Expenses:Books $50.00 $-30.00
+ Assets:Cash $-50.00 $-80.00
+08-Jun-01 June Expenses:Books $60.00 $-20.00
+ Assets:Cash $-60.00 $-80.00
+08-Jun-30 End of June Expenses:Books $60.00 $-20.00
+ Assets:Cash $-60.00 $-80.00
+08-Jul-01 July Expenses:Books $70.00 $-10.00
+ Assets:Cash $-70.00 $-80.00
+08-Jul-31 End of July Expenses:Books $70.00 $-10.00
+ Assets:Cash $-70.00 $-80.00
+08-Aug-01 August Expenses:Books $80.00 0
+ Assets:Cash $-80.00 $-80.00
+08-Aug-31 End of August Expenses:Books $80.00 0
+ Assets:Cash $-80.00 $-80.00
+08-Sep-01 September Expenses:Books $90.00 $10.00
+ Assets:Cash $-90.00 $-80.00
+08-Sep-30 End of September Expenses:Books $90.00 $10.00
+ Assets:Cash $-90.00 $-80.00
+08-Oct-01 October Expenses:Books $100.00 $20.00
+ Assets:Cash $-100.00 $-80.00
+08-Oct-31 End of October Expenses:Books $100.00 $20.00
+ Assets:Cash $-100.00 $-80.00
+08-Nov-01 November Expenses:Books $110.00 $30.00
+ Assets:Cash $-110.00 $-80.00
+08-Nov-30 End of November Expenses:Books $110.00 $30.00
+ Assets:Cash $-110.00 $-80.00
+08-Dec-01 December Expenses:Books $120.00 $40.00
+ Assets:Cash $-120.00 $-80.00
+08-Dec-31 End of December Expenses:Books $120.00 $40.00
+ Assets:Cash $-120.00 $-80.00
+09-Jan-01 January Expenses:Books $10.00 $-70.00
+ Assets:Cash $-10.00 $-80.00
+09-Jan-31 End of January Expenses:Books $10.00 $-70.00
+ Assets:Cash $-10.00 $-80.00
+09-Feb-01 February Expenses:Books $20.00 $-60.00
+ Assets:Cash $-20.00 $-80.00
+09-Feb-28 End of February Expenses:Books $20.00 $-60.00
+ Assets:Cash $-20.00 $-80.00
+09-Mar-01 March Expenses:Books $30.00 $-50.00
+ Assets:Cash $-30.00 $-80.00
+09-Mar-31 End of March Expenses:Books $30.00 $-50.00
+ Assets:Cash $-30.00 $-80.00
+09-Apr-01 April Expenses:Books $40.00 $-40.00
+ Assets:Cash $-40.00 $-80.00
+09-Apr-30 End of April Expenses:Books $40.00 $-40.00
+ Assets:Cash $-40.00 $-80.00
+09-May-01 May Expenses:Books $50.00 $-30.00
+ Assets:Cash $-50.00 $-80.00
+09-May-31 End of May Expenses:Books $50.00 $-30.00
+ Assets:Cash $-50.00 $-80.00
+09-Jun-01 June Expenses:Books $60.00 $-20.00
+ Assets:Cash $-60.00 $-80.00
+09-Jun-30 End of June Expenses:Books $60.00 $-20.00
+ Assets:Cash $-60.00 $-80.00
+09-Jul-01 July Expenses:Books $70.00 $-10.00
+ Assets:Cash $-70.00 $-80.00
+09-Jul-31 End of July Expenses:Books $70.00 $-10.00
+ Assets:Cash $-70.00 $-80.00
+09-Aug-01 August Expenses:Books $80.00 0
+ Assets:Cash $-80.00 $-80.00
+09-Aug-31 End of August Expenses:Books $80.00 0
+ Assets:Cash $-80.00 $-80.00
+09-Sep-01 September Expenses:Books $90.00 $10.00
+ Assets:Cash $-90.00 $-80.00
+09-Sep-30 End of September Expenses:Books $90.00 $10.00
+ Assets:Cash $-90.00 $-80.00
+09-Oct-01 October Expenses:Books $100.00 $20.00
+ Assets:Cash $-100.00 $-80.00
+09-Oct-31 End of October Expenses:Books $100.00 $20.00
+ Assets:Cash $-100.00 $-80.00
+09-Nov-01 November Expenses:Books $110.00 $30.00
+ Assets:Cash $-110.00 $-80.00
+09-Nov-30 End of November Expenses:Books $110.00 $30.00
+ Assets:Cash $-110.00 $-80.00
+09-Dec-01 December Expenses:Books $120.00 $40.00
+ Assets:Cash $-120.00 $-80.00
+09-Dec-31 End of December Expenses:Books $120.00 $40.00
+ Assets:Cash $-120.00 $-80.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-unrealized-gains.test b/test/baseline/opt-unrealized-gains.test
new file mode 100644
index 00000000..5b225a42
--- /dev/null
+++ b/test/baseline/opt-unrealized-gains.test
@@ -0,0 +1,20 @@
+bal -V --unrealized --unrealized-gains G
+<<<
+2008/10/01 Sample
+ Assets:Brokerage 10 AAPL
+ Assets:Checking $-200.00
+
+P 2008/10/20 12:00:00 AAPL $30.00
+
+; 2008/10/20 <Generated Transaction>
+; Assets:Brokerage $100
+; Equity:Unrealized Gains
+>>>1
+ $100.00 Assets
+ $300.00 Brokerage
+ $-200.00 Checking
+ $-100.00 G
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-unrealized-losses.test b/test/baseline/opt-unrealized-losses.test
new file mode 100644
index 00000000..2edd4e63
--- /dev/null
+++ b/test/baseline/opt-unrealized-losses.test
@@ -0,0 +1,20 @@
+bal -V --unrealized --unrealized-losses L
+<<<
+2008/10/01 Sample
+ Assets:Brokerage 10 AAPL
+ Assets:Checking $-200.00
+
+P 2008/10/20 12:00:00 AAPL $10.00
+
+; 2008/10/20 <Generated Transaction>
+; Assets:Brokerage $100
+; Equity:Unrealized Gains
+>>>1
+ $-100.00 Assets
+ $100.00 Brokerage
+ $-200.00 Checking
+ $100.00 L
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-unrealized.test b/test/baseline/opt-unrealized.test
new file mode 100644
index 00000000..c472d9ef
--- /dev/null
+++ b/test/baseline/opt-unrealized.test
@@ -0,0 +1,48 @@
+bal -V --unrealized
+<<<
+2008/10/01 Sample
+ Assets:Brokerage 10 AAPL
+ Assets:Checking $-200.00
+
+P 2008/10/20 12:00:00 AAPL $30.00
+
+; 2008/10/20 <Generated Transaction>
+; Assets:Brokerage $100
+; Equity:Unrealized Gains
+>>>1
+ $100.00 Assets
+ $300.00 Brokerage
+ $-200.00 Checking
+ $-100.00 Equity:Unrealized Gains
+--------------------
+ 0
+>>>2
+=== 0
+bal -V --unrealized --now=2009/11/25
+<<<
+2008/10/01 Sample
+ Assets:Brokerage 10 AAPL
+ Assets:Checking $-200.00
+
+2008/10/01 Sample
+ Assets:Brokerage -10 QQQQ
+ Assets:Checking $1000
+
+P 2008/10/20 12:00:00 AAPL $30.00
+P 2008/10/20 12:00:00 QQQQ $110
+
+; 2008/10/20 <Generated Transaction>
+; Assets:Brokerage $100
+; Equity:Unrealized Gains
+
+; 2008/10/20 <Generated Transaction>
+; Assets:Brokerage $-100
+; Equity:Unrealized Losses
+>>>1
+ 0 Assets
+ $-800.00 Brokerage
+ $800.00 Checking
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/baseline/opt-unround.test b/test/baseline/opt-unround.test
new file mode 100644
index 00000000..70018f12
--- /dev/null
+++ b/test/baseline/opt-unround.test
@@ -0,0 +1,94 @@
+bal --unround --percent
+<<<
+2008/01/11 LIAT
+ Expenses:Travel:Airfare $40.00
+ Liabilities:MasterCard
+
+2008/01/14 cheaptickets.com
+ Expenses:Travel:Airfare $182.19
+ Liabilities:MasterCard
+
+2008/02/05 CTX
+ Expenses:Travel:Auto $240.38
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/05 UNITED
+ Expenses:Travel:Airfare $238.80
+ Liabilities:MasterCard
+
+2008/02/22 BUDGET RENT-A-CAR
+ Expenses:Travel:Auto $40.59
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/03/16 IBERIA
+ Expenses:Travel:Airfare $1,231.60
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/03 AMERICAN
+ Expenses:Travel:Airfare $155.86
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/04/30 UNITED
+ Expenses:Travel:Airfare $437.21
+ Liabilities:MasterCard
+
+2008/08/08 BCIS I-131 FILING FEE-
+ Expenses:Travel:Passport $170.00
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/06 AMERICAN
+ Expenses:Travel:Airfare $912.60
+ Liabilities:MasterCard
+
+2008/09/22 AGNT FEE
+ Expenses:Travel:Airfare $70.00
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 DELTA
+ Expenses:Travel:Airfare $806.20
+ Liabilities:MasterCard
+
+2008/09/22 LIAT 1974 LIMITED
+ Expenses:Travel:Airfare $418.34
+ Liabilities:MasterCard
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+
+2008/12/26 U.S. Department of State
+ Expenses:Travel:Passport $127.00
+ Assets:Checking
+>>>1
+ 100.00% Assets:Checking
+ 100.00% Expenses:Travel
+ 92.14958953% Airfare
+ 3.12882793% Auto
+ 4.72158253% Passport
+ 100.00% Liabilities:MasterCard
+>>>2
+=== 0
diff --git a/test/baseline/opt-weekly.test b/test/baseline/opt-weekly.test
new file mode 100644
index 00000000..fb900c74
--- /dev/null
+++ b/test/baseline/opt-weekly.test
@@ -0,0 +1,225 @@
+reg --weekly books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+07-Dec-30 - 08-Jan-05 Expenses:Books $10.00 $10.00
+08-Jan-27 - 08-Feb-02 Expenses:Books $30.00 $40.00
+08-Feb-24 - 08-Mar-01 Expenses:Books $50.00 $90.00
+08-Mar-30 - 08-Apr-05 Expenses:Books $70.00 $160.00
+08-Apr-27 - 08-May-03 Expenses:Books $90.00 $250.00
+08-May-25 - 08-May-31 Expenses:Books $50.00 $300.00
+08-Jun-01 - 08-Jun-07 Expenses:Books $60.00 $360.00
+08-Jun-29 - 08-Jul-05 Expenses:Books $130.00 $490.00
+08-Jul-27 - 08-Aug-02 Expenses:Books $150.00 $640.00
+08-Aug-31 - 08-Sep-06 Expenses:Books $170.00 $810.00
+08-Sep-28 - 08-Oct-04 Expenses:Books $190.00 $1000.00
+08-Oct-26 - 08-Nov-01 Expenses:Books $210.00 $1210.00
+08-Nov-30 - 08-Dec-06 Expenses:Books $230.00 $1440.00
+08-Dec-28 - 09-Jan-03 Expenses:Books $130.00 $1570.00
+09-Jan-25 - 09-Jan-31 Expenses:Books $10.00 $1580.00
+09-Feb-01 - 09-Feb-07 Expenses:Books $20.00 $1600.00
+09-Feb-22 - 09-Feb-28 Expenses:Books $20.00 $1620.00
+09-Mar-01 - 09-Mar-07 Expenses:Books $30.00 $1650.00
+09-Mar-29 - 09-Apr-04 Expenses:Books $70.00 $1720.00
+09-Apr-26 - 09-May-02 Expenses:Books $90.00 $1810.00
+09-May-31 - 09-Jun-06 Expenses:Books $110.00 $1920.00
+09-Jun-28 - 09-Jul-04 Expenses:Books $130.00 $2050.00
+09-Jul-26 - 09-Aug-01 Expenses:Books $150.00 $2200.00
+09-Aug-30 - 09-Sep-05 Expenses:Books $170.00 $2370.00
+09-Sep-27 - 09-Oct-03 Expenses:Books $190.00 $2560.00
+09-Oct-25 - 09-Oct-31 Expenses:Books $100.00 $2660.00
+09-Nov-01 - 09-Nov-07 Expenses:Books $110.00 $2770.00
+09-Nov-29 - 09-Dec-05 Expenses:Books $230.00 $3000.00
+09-Dec-27 - 10-Jan-02 Expenses:Books $120.00 $3120.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-weekly_empty.test b/test/baseline/opt-weekly_empty.test
new file mode 100644
index 00000000..662f1e14
--- /dev/null
+++ b/test/baseline/opt-weekly_empty.test
@@ -0,0 +1,301 @@
+reg --weekly --empty books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+07-Dec-30 - 08-Jan-05 Expenses:Books $10.00 $10.00
+08-Jan-06 - 08-Jan-12 <None> 0 $10.00
+08-Jan-13 - 08-Jan-19 <None> 0 $10.00
+08-Jan-20 - 08-Jan-26 <None> 0 $10.00
+08-Jan-27 - 08-Feb-02 Expenses:Books $30.00 $40.00
+08-Feb-03 - 08-Feb-09 <None> 0 $40.00
+08-Feb-10 - 08-Feb-16 <None> 0 $40.00
+08-Feb-17 - 08-Feb-23 <None> 0 $40.00
+08-Feb-24 - 08-Mar-01 Expenses:Books $50.00 $90.00
+08-Mar-02 - 08-Mar-08 <None> 0 $90.00
+08-Mar-09 - 08-Mar-15 <None> 0 $90.00
+08-Mar-16 - 08-Mar-22 <None> 0 $90.00
+08-Mar-23 - 08-Mar-29 <None> 0 $90.00
+08-Mar-30 - 08-Apr-05 Expenses:Books $70.00 $160.00
+08-Apr-06 - 08-Apr-12 <None> 0 $160.00
+08-Apr-13 - 08-Apr-19 <None> 0 $160.00
+08-Apr-20 - 08-Apr-26 <None> 0 $160.00
+08-Apr-27 - 08-May-03 Expenses:Books $90.00 $250.00
+08-May-04 - 08-May-10 <None> 0 $250.00
+08-May-11 - 08-May-17 <None> 0 $250.00
+08-May-18 - 08-May-24 <None> 0 $250.00
+08-May-25 - 08-May-31 Expenses:Books $50.00 $300.00
+08-Jun-01 - 08-Jun-07 Expenses:Books $60.00 $360.00
+08-Jun-08 - 08-Jun-14 <None> 0 $360.00
+08-Jun-15 - 08-Jun-21 <None> 0 $360.00
+08-Jun-22 - 08-Jun-28 <None> 0 $360.00
+08-Jun-29 - 08-Jul-05 Expenses:Books $130.00 $490.00
+08-Jul-06 - 08-Jul-12 <None> 0 $490.00
+08-Jul-13 - 08-Jul-19 <None> 0 $490.00
+08-Jul-20 - 08-Jul-26 <None> 0 $490.00
+08-Jul-27 - 08-Aug-02 Expenses:Books $150.00 $640.00
+08-Aug-03 - 08-Aug-09 <None> 0 $640.00
+08-Aug-10 - 08-Aug-16 <None> 0 $640.00
+08-Aug-17 - 08-Aug-23 <None> 0 $640.00
+08-Aug-24 - 08-Aug-30 <None> 0 $640.00
+08-Aug-31 - 08-Sep-06 Expenses:Books $170.00 $810.00
+08-Sep-07 - 08-Sep-13 <None> 0 $810.00
+08-Sep-14 - 08-Sep-20 <None> 0 $810.00
+08-Sep-21 - 08-Sep-27 <None> 0 $810.00
+08-Sep-28 - 08-Oct-04 Expenses:Books $190.00 $1000.00
+08-Oct-05 - 08-Oct-11 <None> 0 $1000.00
+08-Oct-12 - 08-Oct-18 <None> 0 $1000.00
+08-Oct-19 - 08-Oct-25 <None> 0 $1000.00
+08-Oct-26 - 08-Nov-01 Expenses:Books $210.00 $1210.00
+08-Nov-02 - 08-Nov-08 <None> 0 $1210.00
+08-Nov-09 - 08-Nov-15 <None> 0 $1210.00
+08-Nov-16 - 08-Nov-22 <None> 0 $1210.00
+08-Nov-23 - 08-Nov-29 <None> 0 $1210.00
+08-Nov-30 - 08-Dec-06 Expenses:Books $230.00 $1440.00
+08-Dec-07 - 08-Dec-13 <None> 0 $1440.00
+08-Dec-14 - 08-Dec-20 <None> 0 $1440.00
+08-Dec-21 - 08-Dec-27 <None> 0 $1440.00
+08-Dec-28 - 09-Jan-03 Expenses:Books $130.00 $1570.00
+09-Jan-04 - 09-Jan-10 <None> 0 $1570.00
+09-Jan-11 - 09-Jan-17 <None> 0 $1570.00
+09-Jan-18 - 09-Jan-24 <None> 0 $1570.00
+09-Jan-25 - 09-Jan-31 Expenses:Books $10.00 $1580.00
+09-Feb-01 - 09-Feb-07 Expenses:Books $20.00 $1600.00
+09-Feb-08 - 09-Feb-14 <None> 0 $1600.00
+09-Feb-15 - 09-Feb-21 <None> 0 $1600.00
+09-Feb-22 - 09-Feb-28 Expenses:Books $20.00 $1620.00
+09-Mar-01 - 09-Mar-07 Expenses:Books $30.00 $1650.00
+09-Mar-08 - 09-Mar-14 <None> 0 $1650.00
+09-Mar-15 - 09-Mar-21 <None> 0 $1650.00
+09-Mar-22 - 09-Mar-28 <None> 0 $1650.00
+09-Mar-29 - 09-Apr-04 Expenses:Books $70.00 $1720.00
+09-Apr-05 - 09-Apr-11 <None> 0 $1720.00
+09-Apr-12 - 09-Apr-18 <None> 0 $1720.00
+09-Apr-19 - 09-Apr-25 <None> 0 $1720.00
+09-Apr-26 - 09-May-02 Expenses:Books $90.00 $1810.00
+09-May-03 - 09-May-09 <None> 0 $1810.00
+09-May-10 - 09-May-16 <None> 0 $1810.00
+09-May-17 - 09-May-23 <None> 0 $1810.00
+09-May-24 - 09-May-30 <None> 0 $1810.00
+09-May-31 - 09-Jun-06 Expenses:Books $110.00 $1920.00
+09-Jun-07 - 09-Jun-13 <None> 0 $1920.00
+09-Jun-14 - 09-Jun-20 <None> 0 $1920.00
+09-Jun-21 - 09-Jun-27 <None> 0 $1920.00
+09-Jun-28 - 09-Jul-04 Expenses:Books $130.00 $2050.00
+09-Jul-05 - 09-Jul-11 <None> 0 $2050.00
+09-Jul-12 - 09-Jul-18 <None> 0 $2050.00
+09-Jul-19 - 09-Jul-25 <None> 0 $2050.00
+09-Jul-26 - 09-Aug-01 Expenses:Books $150.00 $2200.00
+09-Aug-02 - 09-Aug-08 <None> 0 $2200.00
+09-Aug-09 - 09-Aug-15 <None> 0 $2200.00
+09-Aug-16 - 09-Aug-22 <None> 0 $2200.00
+09-Aug-23 - 09-Aug-29 <None> 0 $2200.00
+09-Aug-30 - 09-Sep-05 Expenses:Books $170.00 $2370.00
+09-Sep-06 - 09-Sep-12 <None> 0 $2370.00
+09-Sep-13 - 09-Sep-19 <None> 0 $2370.00
+09-Sep-20 - 09-Sep-26 <None> 0 $2370.00
+09-Sep-27 - 09-Oct-03 Expenses:Books $190.00 $2560.00
+09-Oct-04 - 09-Oct-10 <None> 0 $2560.00
+09-Oct-11 - 09-Oct-17 <None> 0 $2560.00
+09-Oct-18 - 09-Oct-24 <None> 0 $2560.00
+09-Oct-25 - 09-Oct-31 Expenses:Books $100.00 $2660.00
+09-Nov-01 - 09-Nov-07 Expenses:Books $110.00 $2770.00
+09-Nov-08 - 09-Nov-14 <None> 0 $2770.00
+09-Nov-15 - 09-Nov-21 <None> 0 $2770.00
+09-Nov-22 - 09-Nov-28 <None> 0 $2770.00
+09-Nov-29 - 09-Dec-05 Expenses:Books $230.00 $3000.00
+09-Dec-06 - 09-Dec-12 <None> 0 $3000.00
+09-Dec-13 - 09-Dec-19 <None> 0 $3000.00
+09-Dec-20 - 09-Dec-26 <None> 0 $3000.00
+09-Dec-27 - 10-Jan-02 Expenses:Books $120.00 $3120.00
+>>>2
+=== 0
diff --git a/test/baseline/opt-wide.test b/test/baseline/opt-wide.test
new file mode 100644
index 00000000..02b4284a
--- /dev/null
+++ b/test/baseline/opt-wide.test
@@ -0,0 +1,11 @@
+reg --wide
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+07-Feb-02 RD VMMXX Assets:Investments:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
+ Income:Dividends:Vanguard:VMMXX $-0.35 $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/baseline/opt-yearly.test b/test/baseline/opt-yearly.test
new file mode 100644
index 00000000..a8c73607
--- /dev/null
+++ b/test/baseline/opt-yearly.test
@@ -0,0 +1,198 @@
+reg --yearly books
+<<<
+2008/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2008/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2008/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2008/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2008/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2008/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2008/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2008/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2008/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2008/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2008/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2008/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2008/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/01/01 January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/01/31 End of January
+ Expenses:Books $10.00
+ Assets:Cash
+
+2009/02/01 February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/02/28 End of February
+ Expenses:Books $20.00
+ Assets:Cash
+
+2009/03/01 March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/03/31 End of March
+ Expenses:Books $30.00
+ Assets:Cash
+
+2009/04/01 April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/04/30 End of April
+ Expenses:Books $40.00
+ Assets:Cash
+
+2009/05/01 May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/05/31 End of May
+ Expenses:Books $50.00
+ Assets:Cash
+
+2009/06/01 June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/06/30 End of June
+ Expenses:Books $60.00
+ Assets:Cash
+
+2009/07/01 July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/07/31 End of July
+ Expenses:Books $70.00
+ Assets:Cash
+
+2009/08/01 August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/08/31 End of August
+ Expenses:Books $80.00
+ Assets:Cash
+
+2009/09/01 September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/09/30 End of September
+ Expenses:Books $90.00
+ Assets:Cash
+
+2009/10/01 October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/10/31 End of October
+ Expenses:Books $100.00
+ Assets:Cash
+
+2009/11/01 November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/11/30 End of November
+ Expenses:Books $110.00
+ Assets:Cash
+
+2009/12/01 December
+ Expenses:Books $120.00
+ Assets:Cash
+
+2009/12/31 End of December
+ Expenses:Books $120.00
+ Assets:Cash
+>>>1
+08-Jan-01 - 08-Dec-31 Expenses:Books $1560.00 $1560.00
+09-Jan-01 - 09-Dec-31 Expenses:Books $1560.00 $3120.00
+>>>2
+=== 0
diff --git a/test/baseline/test-sample.dat b/test/baseline/test-sample.dat
new file mode 100644
index 00000000..4bfbe1e2
--- /dev/null
+++ b/test/baseline/test-sample.dat
@@ -0,0 +1,91 @@
+reg
+<<<
+; -*- ledger -*-
+
+N $
+
+= /^Expenses:Books/
+ (Liabilities:Taxes) -0.10
+
+~ Monthly
+ Assets:Bank:Checking $500.00
+ Income:Salary
+
+~ Yearly
+ Expenses:Donations $100.00
+ Assets:Bank:Checking
+
+2004/05/01 * Checking balance
+ Assets:Bank:Checking $1,000.00
+ Equity:Opening Balances
+
+2004/05/03=2004/05/01 * Investment balance
+ Assets:Brokerage 50 AAPL @ $30.00
+ Equity:Opening Balances
+
+2004/05/14 * Páy dày
+ Assets:Bank:Checking 500.00€
+ Income:Salary
+
+2004/05/14 * Another dày in which there is Páying
+ Asséts:Bánk:Chécking:Asséts:Bánk:Chécking $500.00
+ Income:Salary
+
+2004/05/14 * Another dày in which there is Páying
+ РуÑÑкий Ñзык:Ðктивы:РуÑÑкий Ñзык:РуÑÑкий Ñзык $1000.00
+ Income:Salary
+
+tag foo
+
+2004/05/27 Book Store
+ Expenses:Books $20.00
+ Expenses:Cards $40.00
+ Expenses:Docs $30.00
+ Liabilities:MasterCard
+
+end tag
+
+2004/05/27 (100) Credit card company
+ ; This is an xact note!
+ ; Sample: Value
+ Liabilities:MasterCard $20.00
+ ; This is a posting note!
+ ; Sample: Another Value
+ ; :MyTag:
+ Assets:Bank:Checking
+ ; :AnotherTag:
+>>>1
+04-May-01 Checking balance Assets:Bank:Checking $1,000.00 $1,000.00
+ Eq:Opening Balances $-1,000.00 0
+04-May-03 Investment balance Assets:Brokerage 50 AAPL 50 AAPL
+ Eq:Opening Balances $-1,500.00 $-1,500.00
+ 50 AAPL
+04-May-14 Páy dày Assets:Bank:Checking 500.00€ $-1,500.00
+ 50 AAPL
+ 500.00€
+ Income:Salary -500.00€ $-1,500.00
+ 50 AAPL
+04-May-14 Another dày in whic.. ..Bá:Ch:As:Bá:Chécking $500.00 $-1,000.00
+ 50 AAPL
+ Income:Salary $-500.00 $-1,500.00
+ 50 AAPL
+04-May-14 Another dày in whic.. Ру:Ðк:Ру:РуÑÑкий Ñзык $1,000.00 $-500.00
+ 50 AAPL
+ Income:Salary $-1,000.00 $-1,500.00
+ 50 AAPL
+04-May-27 Book Store Expenses:Books $20.00 $-1,480.00
+ 50 AAPL
+ Expenses:Cards $40.00 $-1,440.00
+ 50 AAPL
+ Expenses:Docs $30.00 $-1,410.00
+ 50 AAPL
+ Liabilities:MasterCard $-90.00 $-1,500.00
+ 50 AAPL
+ (Liabilities:Taxes) $-2.00 $-1,502.00
+ 50 AAPL
+04-May-27 Credit card company Liabilities:MasterCard $20.00 $-1,482.00
+ 50 AAPL
+ Assets:Bank:Checking $-20.00 $-1,502.00
+ 50 AAPL
+>>>2
+=== 0
diff --git a/test/convert.py b/test/convert.py
new file mode 100755
index 00000000..05a62b7e
--- /dev/null
+++ b/test/convert.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+
+# convert.py: This script converts a C++ Ledger unit test into an equivalent
+# Python unit test.
+#
+# Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC nor the names of its
+# 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.
+
+import re
+import sys
+import os
+
+source = os.path.abspath(sys.argv[1])
+base = os.path.splitext(source)[0]
+target = os.path.abspath(sys.argv[2])
+
+dirname = os.path.dirname(target)
+if not os.path.isdir(dirname):
+ try: os.makedirs(dirname)
+ except: pass
+
+fd = open(source, "r")
+fo = open(target, "w")
+
+fo.write('''# -*- coding: utf-8 -*-
+
+import unittest
+import exceptions
+import operator
+
+from ledger import *
+from StringIO import *
+from datetime import *
+
+internalAmount = Amount.exact
+
+class %sTestCase(unittest.TestCase):
+ testSession = None
+
+ def assertValid(self, amt):
+ self.assertTrue(amt.valid())''' % os.path.basename(base))
+
+not_for_python = 0
+
+for line in fd.readlines():
+ if re.match('^#ifndef NOT_FOR_PYTHON', line):
+ not_for_python += 1
+ continue
+ elif not_for_python > 0:
+ if re.match('^#endif // NOT_FOR_PYTHON', line):
+ not_for_python -= 1
+ continue
+
+ if re.match('^(using|CPP|[#{}/])', line):
+ continue
+ if re.match('^\s+[{}]\s+$', line):
+ continue
+
+ if not re.search('assert', line):
+ match = re.match('void [^:]+::(test[^(]+|setUp|tearDown)\(\)', line)
+ if match:
+ fo.write(' def %s(self):\n' % match.group(1))
+ continue
+
+ match = re.search(' ([a-z:_<>]+?)&?\s+([a-z0-9_]+)(\((.+?)\))?;', line)
+ if match:
+ if match.group(1) != "std::string":
+ line = ' %s = %s(%s)\n' % (match.group(2), match.group(1),
+ match.group(4) or "")
+ else:
+ line = ''
+
+ match = re.search(' ([a-z:_<>]+?)&?\s+([a-z0-9]+)\s*=\s*([^(]+);', line)
+ if match:
+ line = ' %s = %s(%s)\n' % (match.group(2), match.group(1),
+ match.group(3))
+
+ match = re.search(' ([a-z:_<>]+?)\s+([a-z0-9]+)\s*=\s*(.+?)$', line)
+ if match:
+ line = ' %s = %s\n' % (match.group(2), match.group(3))
+
+ line = re.sub('CPPUNIT_ASSERT', 'self.assertTrue', line)
+ line = re.sub('assertValid', 'self.assertValid', line)
+ line = re.sub('assertTrue', 'self.assertTrue', line)
+ line = re.sub('assertFalse', 'self.assertFalse', line)
+ line = re.sub('assertNotEqual', 'self.assertNotEqual', line)
+ line = re.sub('assertEqual', 'self.assertEqual', line)
+ line = re.sub('assertThrow\(([^,]+), ([^,)]+?)\)',
+ 'self.assertRaises(\\2, lambda: \\1)', line)
+ #line = re.sub('optional<([^>]+?)>', '\\1', line)
+ line = re.sub('amount_t::precision_t\(([^)]+?)\)', '\\1', line)
+
+ # Determine this list automatically by scanning the class_ lines in
+ # src/py_*.cc
+ line = re.sub('amount_t::', 'Amount.', line)
+ line = re.sub('Amount\.PARSE_', 'AmountParse.', line)
+ line = re.sub('commodity_t\(([^)]+?)\)', '\\1', line)
+ line = re.sub('commodity_t::', 'Commodity.', line)
+ line = re.sub('balance_t::', 'Balance.', line)
+ line = re.sub('balance_pair_t::', 'BalancePair.', line)
+ line = re.sub('value_t::', 'Value.', line)
+
+ line = re.sub('amount_t', 'Amount', line)
+ line = re.sub('commodity_t', 'Commodity', line)
+ line = re.sub('balance_t', 'Balance', line)
+ line = re.sub('balance_pair_t', 'BalancePair', line)
+ line = re.sub('value_t', 'Value', line)
+
+ line = re.sub("PARSE_DEFAULT", "ParseFlags.Default", line)
+ line = re.sub("PARSE_PARTIAL", "ParseFlags.Partial", line)
+ line = re.sub("PARSE_SINGLE", "ParseFlags.Single", line)
+ line = re.sub("PARSE_NO_MIGRATE", "ParseFlags.NoMigrate", line)
+ line = re.sub("PARSE_NO_REDUCE", "ParseFlags.NoReduce", line)
+ line = re.sub("PARSE_NO_ASSIGN", "ParseFlags.NoAssign", line)
+ line = re.sub("PARSE_NO_DATES", "ParseFlags.NoDates", line)
+ line = re.sub("PARSE_OP_CONTEXT", "ParseFlags.OpContext", line)
+ line = re.sub("PARSE_SOFT_FAIL", "ParseFlags.SoftFail", line)
+
+ line = re.sub('ledger::', '', line)
+ line = re.sub('std::istringstream', 'StringIO', line)
+ line = re.sub('std::ostringstream', 'StringIO', line)
+ line = re.sub('set_session_context\(&session\)',
+ 'self.testSession = session()\n set_session_context(self.testSession)', line)
+ line = re.sub('set_session_context\(\)',
+ 'set_session_context()\n self.testSession = None', line)
+ line = re.sub('([a-z_]+?)_t\b', '\\1', line)
+ line = re.sub('("[^"]+")', 'u\\1', line)
+ line = re.sub('std::string\(([^)]+?)\)', '\\1', line)
+ line = re.sub('string\(([^)]+?)\)', '\\1', line)
+ line = re.sub('\.print\(([^)]+?)\)', '.print_(\\1)', line)
+ line = re.sub('true', 'True', line)
+ line = re.sub('false', 'False', line)
+ line = re.sub('CURRENT_TIME\(\)', 'datetime.now()', line)
+ line = re.sub('CURRENT_DATE\(\)', 'date.today()', line)
+ line = re.sub('commodity\(\)', 'commodity', line)
+ line = re.sub('precision\(\)', 'precision', line)
+ line = re.sub('([0-9]+)[FL]', '\\1', line)
+ line = re.sub('([0-9]+)UL', '\\1L', line)
+ line = re.sub(';', '', line)
+ line = re.sub('//', '#', line)
+ line = re.sub('->', '.', line)
+ line = re.sub('(\s+|\()(\S+?) \? (.+?) : (.+?)\)',
+ '\\1\\3 if \\2 else \\4)', line)
+ line = re.sub('if \((.+?)\)( {)?$', 'if \\1:', line)
+ line = re.sub('(} )?else( {)?$', 'else:', line)
+
+ line = re.sub('amount_error', 'exceptions.ArithmeticError', line)
+
+ match = re.match('^ ', line)
+ if match:
+ fo.write(' ' + line)
+ else:
+ fo.write(line)
+
+fo.write('''
+
+def suite():
+ return unittest.TestLoader().loadTestsFromTestCase(%sTestCase)
+
+if __name__ == '__main__':
+ unittest.main()
+''' % os.path.basename(base))
+
+fo.close()
+fd.close()
diff --git a/test/fullcheck.sh b/test/fullcheck.sh
new file mode 100755
index 00000000..f3c20dd2
--- /dev/null
+++ b/test/fullcheck.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+VALGRIND=''
+if [ -x /usr/bin/valgrind ]; then
+ VALGRIND=valgrind
+fi
+
+export MallocGuardEdges=1
+export MallocScribble=1
+export MallocPreScribble=1
+export MallocCheckHeapStart=100
+export MallocCheckHeapEach=100
+export DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib
+export MALLOC_PROTECT_BEFORE=1
+export MALLOC_FILL_SPACE=1
+export MALLOC_STRICT_SIZE=1
+
+exec $VALGRIND $@
diff --git a/test/input/drewr.dat b/test/input/drewr.dat
new file mode 100644
index 00000000..13b88844
--- /dev/null
+++ b/test/input/drewr.dat
@@ -0,0 +1,63 @@
+; -*- ledger -*-
+
+= account =~ /^Income/
+ (Liabilities:Tithe) 0.12
+
+~ Monthly
+ Assets:Checking $500.00
+ Income:Salary
+
+2003/12/01 * Checking balance
+ Assets:Checking $1,000.00
+ Equity:Opening Balances
+
+2003/12/20 Organic Co-op
+ Expenses:Food:Groceries $ 37.50 ; [=2004/01/01]
+ Expenses:Food:Groceries $ 37.50 ; [=2004/02/01]
+ Expenses:Food:Groceries $ 37.50 ; [=2004/03/01]
+ Expenses:Food:Groceries $ 37.50 ; [=2004/04/01]
+ Expenses:Food:Groceries $ 37.50 ; [=2004/05/01]
+ Expenses:Food:Groceries $ 37.50 ; [=2004/06/01]
+ Assets:Checking $ -225.00
+
+2003/12/28=2004/01/01 Acme Mortgage
+ Liabilities:Mortgage:Principal $ 200.00
+ Expenses:Interest:Mortgage $ 500.00
+ Expenses:Escrow $ 300.00
+ Assets:Checking $ -1000.00
+
+2004/01/02 Grocery Store
+ Expenses:Food:Groceries $ 65.00
+ Assets:Checking
+
+2004/01/05 Employer
+ Assets:Checking $ 2000.00
+ Income:Salary
+
+2004/01/14 Bank
+ ; Regular monthly savings transfer
+ Assets:Savings $ 300.00
+ Assets:Checking
+
+2004/01/19 Grocery Store
+ Expenses:Food:Groceries $ 44.00
+ Assets:Checking
+
+2004/01/25 Bank
+ ; Transfer to cover car purchase
+ Assets:Checking $ 5,500.00
+ Assets:Savings
+ ; :nobudget:
+
+2004/01/25 Tom's Used Cars
+ Expenses:Auto $ 5,500.00
+ ; :nobudget:
+ Assets:Checking
+
+2004/01/27 Book Store
+ Expenses:Books $20.00
+ Liabilities:MasterCard
+
+2004/02/01 Sale
+ Assets:Checking:Business $ 30.00
+ Income:Sales
diff --git a/test/input/sample.dat b/test/input/sample.dat
new file mode 100644
index 00000000..12ac4cb4
--- /dev/null
+++ b/test/input/sample.dat
@@ -0,0 +1,54 @@
+; -*- ledger -*-
+
+N $
+
+= /^Expenses:Books/
+ (Liabilities:Taxes) -0.10
+
+~ Monthly
+ Assets:Bank:Checking $500.00
+ Income:Salary
+
+~ Yearly
+ Expenses:Donations $100.00
+ Assets:Bank:Checking
+
+2004/05/01 * Checking balance
+ Assets:Bank:Checking $1,000.00
+ Equity:Opening Balances
+
+2004/05/03=2004/05/01 * Investment balance
+ Assets:Brokerage 50 AAPL @ $30.00
+ Equity:Opening Balances
+
+2004/05/14 * Páy dày
+ Assets:Bank:Checking 500.00€
+ Income:Salary
+
+2004/05/14 * Another dày in which there is Páying
+ Asséts:Bánk:Chécking:Asséts:Bánk:Chécking $500.00
+ Income:Salary
+
+2004/05/14 * Another dày in which there is Páying
+ РуÑÑкий Ñзык:Ðктивы:РуÑÑкий Ñзык:РуÑÑкий Ñзык $1000.00
+ Income:Salary
+
+tag foo
+
+2004/05/27 Book Store
+ Expenses:Books $20.00
+ Expenses:Cards $40.00
+ Expenses:Docs $30.00
+ Liabilities:MasterCard
+
+end tag
+
+2004/05/27 (100) Credit card company
+ ; This is an xact note!
+ ; Sample: Value
+ Liabilities:MasterCard $20.00
+ ; This is a posting note!
+ ; Sample: Another Value
+ ; :MyTag:
+ Assets:Bank:Checking
+ ; :AnotherTag:
diff --git a/test/input/standard.dat b/test/input/standard.dat
new file mode 100644
index 00000000..62fa7f86
--- /dev/null
+++ b/test/input/standard.dat
@@ -0,0 +1,5619 @@
+2002/01/01 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ af0628973ff35bd62ddb048fa41dd8d83c1c46fe $474.31
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/03/01 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $14.91
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/03/09 * 4891c3f867e3d91808f83da388a5ba439aedba80
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $1,173.15
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/03/09 * 2fb83b483eeab9d98529783900fa85eb4348d991
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $693.23
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/03/09 * 20bc87fd47b41f9abf6815df7496e90345f7ed37
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $64.00
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/05/18 * 4891c3f867e3d91808f83da388a5ba439aedba80
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $481.25
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/05/18 * 2fb83b483eeab9d98529783900fa85eb4348d991
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $357.93
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/09/14 * 20bc87fd47b41f9abf6815df7496e90345f7ed37
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $32.00
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/09/14 * 2fb83b483eeab9d98529783900fa85eb4348d991
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $338.83
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/09/14 * 4891c3f867e3d91808f83da388a5ba439aedba80
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $481.25
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/09/30 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ c56a21d23a6535184e7152ee138c28974f14280c 866.231000 GGGGG
+ a35e82730cf91569c302b313780e5895f75a62b9 $-17,783.72
+
+2002/09/30 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ c56a21d23a6535184e7152ee138c28974f14280c 1,925.940000 AAAAA
+ a35e82730cf91569c302b313780e5895f75a62b9 $-33,299.47
+
+2002/09/30 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ c56a21d23a6535184e7152ee138c28974f14280c 564.042000 EEEEE
+ a35e82730cf91569c302b313780e5895f75a62b9 $-15,810.10
+
+2002/10/01 * db16aa488f49561098cd08c4749d94256c733b64
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d $450.00
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a
+
+2002/10/01 * d11efaa25b28e9aa5bd7b020f70f161cb43d3e7d
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a $900.00
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/10/18 * 4891c3f867e3d91808f83da388a5ba439aedba80
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $343.75
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/10/19 * b007369e15aba78cb6075310da96b854f5448a3a
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $17.59
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/10/20 * 4891c3f867e3d91808f83da388a5ba439aedba80
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $137.50
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/10/25 * 2fb83b483eeab9d98529783900fa85eb4348d991
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $589.40
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/10/25 * 4891c3f867e3d91808f83da388a5ba439aedba80
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $354.36
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/10/27 * (2031) d1704e602da55041cc9c5f83a1076b1551c1225a
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a $900.00
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/10/31 * db16aa488f49561098cd08c4749d94256c733b64
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d $450.00
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a
+
+2002/11/30 * db16aa488f49561098cd08c4749d94256c733b64
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d $450.00
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a
+
+2002/12/17 * f94418bf56f6656f43bac8f2b9bf4ce940614f44
+ 0a014a93e9bf8b2b56afd4ffeeeca7da7d3af3fd $39.90
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2002/12/22 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ 7826c9ce60ae644a02466043232f592994802448 82.288 CCCCC
+ a35e82730cf91569c302b313780e5895f75a62b9 $-1,465.55
+
+2002/12/22 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ c0226fafdf9e6711ac9121cf263e2d50791859cb 1,012.251 CCCCC
+ a35e82730cf91569c302b313780e5895f75a62b9 $-18,028.19
+
+2002/12/24 * fa73d67b17a393d9db8c96a9f3ec222804fe0fda
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $128.45
+ f0d45665b22d0562833aa3bf373c5b15640d833e $64.22
+ 4907823cffe667ad9decdcdd3a4780c15485c6ea $-128.45
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $-64.22
+
+2002/12/25 * 7592910fc29b651a46c7c700406ed51978ae4cd6
+ f0d45665b22d0562833aa3bf373c5b15640d833e $11.53
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2002/12/28 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ f0d45665b22d0562833aa3bf373c5b15640d833e $11.68
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2002/12/30 * 580e3cdf2e29864c0c1abfde600494a83263c68a
+ f0d45665b22d0562833aa3bf373c5b15640d833e $15.40
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2002/12/31 * 32fcd74c867c3ddbff9b8d38e8294d6727b1f3a2
+ e5dfa7a292da1dd185fc7c6dd2402ec582a15f37 $20.00
+ 88671479b5cf1fbd5df40139835b336f10e4c7a1
+
+2002/12/31 * db16aa488f49561098cd08c4749d94256c733b64
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $450.00
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a
+
+2002/12/31 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ 15d4990b82d33262ff733b3e6539d66a0445c193 $1,200.04
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/12/31 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d $484.29
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2002/12/31 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $13,692.31
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/12/31 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d $82,589.97
+ f0d45665b22d0562833aa3bf373c5b15640d833e
+
+2002/12/31 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ (845ac5d9910830a5764c934bf791195b0fcd91f4) $-18,384.85
+
+2002/12/31 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $7,650.70
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2002/12/31 * (2097) 098d6e0cbcd5aebfbcdb912993e2d789e30f3a81
+ 3e2706db92ca6bb952333fd028e582695910c01d $55.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/01 * 95b6b46bf9f262cf7aeffa04ba12d3bde9411eb6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $87.21
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/01 * b7d9ccca2f575498c7c0e626d96c97b2735ee398
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d $3,000.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/01 * 8c40cce6f07a195ac21076a3f150035c65264aa8
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $77,589.97
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2003/01/01 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $1,812.50
+ 15d4990b82d33262ff733b3e6539d66a0445c193 $600.02
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $539.70
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $245.00
+ a64166a90252d444071c62e9e0746ce6e83234b6 $57.30
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $97.15
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $48.46
+ c56a21d23a6535184e7152ee138c28974f14280c $600.02
+ (845ac5d9910830a5764c934bf791195b0fcd91f4) $114.00
+ 39189083b8637c7fff89e6bcf808790861417796 $-4,000.15
+
+2003/01/01 * 91361769cb74ddd9f9fc545ca4f1bc4e4d7d7212
+ c56a21d23a6535184e7152ee138c28974f14280c $120.01
+ 775a73f9b8633e396be7cfd03b6a46f07b47c5ef
+
+2003/01/01 * (2089) e48c080a9f967951944a3ecd5d6e6bf1d296725f
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $21.51
+ f0d45665b22d0562833aa3bf373c5b15640d833e $21.51
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-43.02
+
+2003/01/01 * (2098) d1704e602da55041cc9c5f83a1076b1551c1225a
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a $450.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/01 * 04ff4313e11dca88fb1707316329ff143f8f78c2
+ f0d45665b22d0562833aa3bf373c5b15640d833e $19.01
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/02 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ 64feb5a551f10cc181b37cc3af9d95c82e48a916 $5.00
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2003/01/02 * c724d9c91df5cb3bd4441a2cd9e15676c61555f7
+ f0d45665b22d0562833aa3bf373c5b15640d833e $30.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/02 * c724d9c91df5cb3bd4441a2cd9e15676c61555f7
+ f0d45665b22d0562833aa3bf373c5b15640d833e $367.75
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/02 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ f0d45665b22d0562833aa3bf373c5b15640d833e $36.16
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/02 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ f0d45665b22d0562833aa3bf373c5b15640d833e $12.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/02 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 5.838000 EEEEE
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.00
+
+2003/01/02 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 8.262000 GGGGG
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.02
+
+2003/01/02 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 18.930000 AAAAA
+ c56a21d23a6535184e7152ee138c28974f14280c $-360.01
+
+2003/01/03 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.16
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-60.16
+
+2003/01/04 * 268fe8c09361043234b89aa2d55fd25091b851e1
+ f0d45665b22d0562833aa3bf373c5b15640d833e $4.93
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/04 * e77f5f8a743363bfb4938ddfd5f7ae8f5b370fad
+ f0d45665b22d0562833aa3bf373c5b15640d833e $12.06
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/05 * (2099) 74f61fee296e715055dc0f5ae30804ae450fb7dc
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $100,000.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/05 * 32c8ced97c0cde788ffc072673579337197ecc71
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $8,210.09
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $3,400.62
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $20.68
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $1,552.69
+ a64166a90252d444071c62e9e0746ce6e83234b6 $182.63
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $780.89
+ ef4f24d74e0801474c3d039fbb4df9ebecd5de52 $-12,594.91
+ f0d45665b22d0562833aa3bf373c5b15640d833e $-1,552.69
+
+2003/01/05 * e65f77390d2ff7c7040d6fed1a6b62d5ba027748
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $200.00
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $100.00
+ af0628973ff35bd62ddb048fa41dd8d83c1c46fe $-200.00
+ f0d45665b22d0562833aa3bf373c5b15640d833e $-100.00
+
+2003/01/05 * c94f479833c5d401cffdfa7afe6c9c2d56448019
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $21.94
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2003/01/05 * 504c6c141d7ed2aa8a8a8786be2225c39cee7a0f
+ 88671479b5cf1fbd5df40139835b336f10e4c7a1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/05 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $18.61
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/05 * (2100) 7994a463ade0f972bf1bb59ac236e37b08bfc4d7
+ 904eafc4a3d3e7ee665de39f7baa66d9785b3c98 $178.67
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/05 * (2101) 39edcef4400a8d5b613da37c354870d87f6b60b8
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $15.00
+ f0d45665b22d0562833aa3bf373c5b15640d833e $7.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-15.00
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $-7.50
+
+2003/01/05 * (2102) 03642d4c8cfd39cbe8e1bbce3179a0ca53935e30
+ f0d45665b22d0562833aa3bf373c5b15640d833e $1,500.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/06 * 8c40cce6f07a195ac21076a3f150035c65264aa8
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $2,537.79
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2003/01/06 * 95b6b46bf9f262cf7aeffa04ba12d3bde9411eb6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $128.91
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/06 * 8c40cce6f07a195ac21076a3f150035c65264aa8
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $103,789.94
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d
+
+2003/01/07 * 6f3e9ddd855e82d1ec25ed14b2180d34b08f1045
+ f0d45665b22d0562833aa3bf373c5b15640d833e $26.19
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/07 * eacc3fc8d502d7f4e62f04f1325b9f5f463cc387
+ f0d45665b22d0562833aa3bf373c5b15640d833e $3.22
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/07 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.75
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/07 * (2095) 03642d4c8cfd39cbe8e1bbce3179a0ca53935e30
+ f0d45665b22d0562833aa3bf373c5b15640d833e $82,589.97
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/08 * (2103) 35b7ad4a355641a58d7ef29cce5ce8dadc550d35
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $190.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/09 * fa39c23bd7d06b52f53d88060f6522ed961cc7e8
+ f0d45665b22d0562833aa3bf373c5b15640d833e $12.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/09 * b1b4091f86e761f140374909aeb031bfe4ddf404
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $19.54
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/10 * 028eaa2ba85404a279ea2978142c687b0a75dff3
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.45
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/10 * 65646e6c930f4d0d52f63a610acf04138d855930
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $16.14
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/11 * 0fb419d273cdd0cfe9825e94f91c2058e99c1f7a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $33.41
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/12 * 38be5d47bdf3f41c49d0d4bd5cce5fa442098349
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $32.93
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $16.46
+ e8a7204939bd995e0343c42de4366ad4fb95fe4d $-32.93
+ f0d45665b22d0562833aa3bf373c5b15640d833e $-16.46
+
+2003/01/12 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $137.74
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/01/12 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.01
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-34.01
+
+2003/01/12 * 405295e72fc5fb41cb97a68a217108b08b4e045e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.78
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/12 * 8f7e593a4e05c2cf160d61d4a8b556368f0d7818
+ fc0e191163be4d1966e3c51b1635401f9e82a807 1,558.89 BRSIX
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $-13,500.00
+
+2003/01/12 * (2096) fa73d67b17a393d9db8c96a9f3ec222804fe0fda
+ 4907823cffe667ad9decdcdd3a4780c15485c6ea $128.45
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/13 * 31eeb3d4b0873efdd0c81d86a5f1cc13585d192f
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $23.63
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/13 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.41
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-71.41
+
+2003/01/13 * 4c0edf908955202437646c30421cdd92f4fe3088
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $75.00
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/01/14 * a46af6931d9dace2200617548fab3274549e308f
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $75.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/14 * (2104) fa73d67b17a393d9db8c96a9f3ec222804fe0fda
+ 4907823cffe667ad9decdcdd3a4780c15485c6ea $105.17
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/15 * 31eeb3d4b0873efdd0c81d86a5f1cc13585d192f
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $16.12
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/15 * (2106) 619cbfd21d72639f985324a9306696ce1262f3f6
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $5,000.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/15 * bf5312fa21eac164606692125d69af404878faa1
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $50.00
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb
+
+2003/01/15 * (2105) 4ffc4349510313ea639fc1e50d7e156c456cdb84
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $60.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/15 * bea8d5e2678e516790a1d65f5c22875c1ee81f09
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $100.00
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb
+
+2003/01/15 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $1,812.49
+ 15d4990b82d33262ff733b3e6539d66a0445c193 $600.02
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $539.70
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $245.01
+ a64166a90252d444071c62e9e0746ce6e83234b6 $57.30
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $97.15
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $48.46
+ c56a21d23a6535184e7152ee138c28974f14280c $600.02
+ (845ac5d9910830a5764c934bf791195b0fcd91f4) $114.00
+ 39189083b8637c7fff89e6bcf808790861417796 $-4,000.15
+
+2003/01/15 * 91361769cb74ddd9f9fc545ca4f1bc4e4d7d7212
+ c56a21d23a6535184e7152ee138c28974f14280c $120.01
+ 775a73f9b8633e396be7cfd03b6a46f07b47c5ef
+
+2003/01/15 * f50bc0cf6300861a90dc5b29443cd614a09ffd88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $484.29
+ f0d45665b22d0562833aa3bf373c5b15640d833e $242.14
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-484.29
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $-242.14
+
+2003/01/16 * 2fac90ee40cd30ece1ad465f69e2d84d5ae64a9c
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $3.79
+ e8a7204939bd995e0343c42de4366ad4fb95fe4d
+
+2003/01/16 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 5.871000 EEEEE
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.00
+
+2003/01/16 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 18.970000 AAAAA
+ c56a21d23a6535184e7152ee138c28974f14280c $-360.01
+
+2003/01/16 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 8.389000 GGGGG
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.02
+
+2003/01/16 * 6045e146184c24b57b23831ab235fe447eb5b221
+ 181884ada86d2c3e7511e3ef3830fcf9f75b1421 $11.40
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/17 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $24.02
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-44.02
+
+2003/01/18 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $20.44
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/18 * 8c959e2ec53ec728cb1dec19971a950359c82e02
+ ca268d538b1a0056c1e3c8c5874d4cb30452d738 $40.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/19 * fa73d67b17a393d9db8c96a9f3ec222804fe0fda
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $105.17
+ 4907823cffe667ad9decdcdd3a4780c15485c6ea
+
+2003/01/20 * (101) d65a386cd0aaed34259bb2207516b1f81a0cb53c
+ 3baf6f27bea8f4639c5e61228227dc8bfa2c46a5 $25,000.00
+ (845ac5d9910830a5764c934bf791195b0fcd91f4) $25,000.00
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78
+
+2003/01/21 * 856c722d0a5c00b903ab4d7c2f93505edb13bb93
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.71
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $35.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-54.71
+
+2003/01/22 * 8f7e593a4e05c2cf160d61d4a8b556368f0d7818
+ fc0e191163be4d1966e3c51b1635401f9e82a807 -1,558.89 BRSIX
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $13,281.74
+
+2003/01/24 * 42939113edd815fec10f655034af3c7864bcb951
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/24 * 1e49e75ca9266dcd066c3f935f6cf6c6156f97c7
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.77
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/25 * a0cdc203f150cf807d3fc44540ccb28e6270e47a
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $8.34
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/27 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $2.25
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-102.25
+
+2003/01/27 * c820efeab420f1943da93ef6a80fa5867d2cce68
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $22.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/29 * 6e86042aa3127e49456b188a9c8d7c41f8c017d4
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $0.73
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/01/29 * 625a740024b74b8dd4d98b56b5efe171f3f5c9cc
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $265.64
+ fc0e191163be4d1966e3c51b1635401f9e82a807
+
+2003/01/29 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $1,811.55
+ 15d4990b82d33262ff733b3e6539d66a0445c193 $600.02
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $539.70
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $245.79
+ a64166a90252d444071c62e9e0746ce6e83234b6 $57.46
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $97.15
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $48.46
+ c56a21d23a6535184e7152ee138c28974f14280c $600.02
+ (845ac5d9910830a5764c934bf791195b0fcd91f4) $114.00
+ 39189083b8637c7fff89e6bcf808790861417796 $-4,000.15
+
+2003/01/29 * 91361769cb74ddd9f9fc545ca4f1bc4e4d7d7212
+ c56a21d23a6535184e7152ee138c28974f14280c $120.01
+ 775a73f9b8633e396be7cfd03b6a46f07b47c5ef
+
+2003/01/30 * 5030f5a1c32cc3fa29ad77aefd16fa3a8ed3c666
+ 0a014a93e9bf8b2b56afd4ffeeeca7da7d3af3fd $13.45
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/01/30 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 8.764000 GGGGG
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.02
+
+2003/01/30 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 19.890000 AAAAA
+ c56a21d23a6535184e7152ee138c28974f14280c $-360.01
+
+2003/01/30 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 6.164000 EEEEE
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.00
+
+2003/01/30 * 2fac90ee40cd30ece1ad465f69e2d84d5ae64a9c
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $1.98
+ e8a7204939bd995e0343c42de4366ad4fb95fe4d
+
+2003/01/30 * 32c8ced97c0cde788ffc072673579337197ecc71
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $425.81
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $1,898.27
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $1,571.69
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $19.95
+ a64166a90252d444071c62e9e0746ce6e83234b6 $84.41
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $360.91
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $3,358.30
+ ef4f24d74e0801474c3d039fbb4df9ebecd5de52 $-5,821.07
+ f0d45665b22d0562833aa3bf373c5b15640d833e $-1,898.27
+
+2003/01/30 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.69
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/01/31 * 32fcd74c867c3ddbff9b8d38e8294d6727b1f3a2
+ e5dfa7a292da1dd185fc7c6dd2402ec582a15f37 $20.00
+ 88671479b5cf1fbd5df40139835b336f10e4c7a1
+
+2003/01/31 * db16aa488f49561098cd08c4749d94256c733b64
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $450.00
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a
+
+2003/02/01 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $13.84
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/02 * 3448304b899a638ade73b30d085269b8c8651c8d
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $16,450.00
+ fc0e191163be4d1966e3c51b1635401f9e82a807
+
+2003/02/03 * (2107) a4c1053a2870f13b1bfdd38db80b5d72acfba4d2
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $55.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/03 * bce0a909463614ce1a6b6b8dc4ae66a3cf232086
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $11.47
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/03 * c50ffe9fd9ab159d36900b2a90d0db4ddf70311e
+ 10cab4f7105feed78ca34f97ba79d013cb8e28f4 $8.61
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/03 * (2108) d1704e602da55041cc9c5f83a1076b1551c1225a
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a $450.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/05 * 504c6c141d7ed2aa8a8a8786be2225c39cee7a0f
+ 88671479b5cf1fbd5df40139835b336f10e4c7a1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/06 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.95
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/06 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $2.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-102.00
+
+2003/02/07 * 38bf98a7f1e072558f56cd895247f2b03b533559
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.21
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/07 * fa39c23bd7d06b52f53d88060f6522ed961cc7e8
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $22.44
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/07 * 1b0cfd69357b7c20fb55adfc8fe5afa6ddffe80a
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $35.49
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/09 * 222db0fc1cadf0af4ccdbccb7ecbb0aa86efb2fe
+ 9e67321982e83628563e8a2b396325aa18283ba5 $26.13
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/09 * c7766c8fa1a0a32c2c7f3a3fefbb0840e0802cca
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.20
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/09 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $22.33
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/09 * 3448304b899a638ade73b30d085269b8c8651c8d
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $5,400.00
+ fc0e191163be4d1966e3c51b1635401f9e82a807
+
+2003/02/09 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $0.49
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/02/10 * (2109) a4c1053a2870f13b1bfdd38db80b5d72acfba4d2
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $58.80
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/11 * 606d337268d95afe2603939a623db0813eba2651
+ 9e67321982e83628563e8a2b396325aa18283ba5 $234.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/12 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $1,812.49
+ 15d4990b82d33262ff733b3e6539d66a0445c193 $600.02
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $539.70
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $245.01
+ a64166a90252d444071c62e9e0746ce6e83234b6 $57.30
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $97.15
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $48.46
+ c56a21d23a6535184e7152ee138c28974f14280c $600.02
+ (845ac5d9910830a5764c934bf791195b0fcd91f4) $114.00
+ 39189083b8637c7fff89e6bcf808790861417796 $-4,000.15
+
+2003/02/12 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $1,560.56
+ 15d4990b82d33262ff733b3e6539d66a0445c193 $514.59
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $926.25
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $212.69
+ a64166a90252d444071c62e9e0746ce6e83234b6 $49.75
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $166.73
+ e49713c1693a3eeddb9cef202706e9d1a44cc481 $-3,430.57
+
+2003/02/12 * 91361769cb74ddd9f9fc545ca4f1bc4e4d7d7212
+ c56a21d23a6535184e7152ee138c28974f14280c $120.01
+ 775a73f9b8633e396be7cfd03b6a46f07b47c5ef
+
+2003/02/12 * d2667e42a8beac84d6f95887ab807a947a425d67
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $48.51
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/13 * 31eeb3d4b0873efdd0c81d86a5f1cc13585d192f
+ 9e67321982e83628563e8a2b396325aa18283ba5 $17.20
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/15 * 0f4b0afecf3d935e7bc810e1e0920cc8ee6f15ec
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $64.56
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/16 * f50bc0cf6300861a90dc5b29443cd614a09ffd88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $603.31
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/16 * bea8d5e2678e516790a1d65f5c22875c1ee81f09
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $100.00
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb
+
+2003/02/16 * (2110) a4c1053a2870f13b1bfdd38db80b5d72acfba4d2
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $19.60
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/16 * (2111) fa73d67b17a393d9db8c96a9f3ec222804fe0fda
+ 4907823cffe667ad9decdcdd3a4780c15485c6ea $132.77
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/16 * (2112) 7994a463ade0f972bf1bb59ac236e37b08bfc4d7
+ 904eafc4a3d3e7ee665de39f7baa66d9785b3c98 $119.12
+ 628072f9bfc87daeb5e0144ef2090ef8057935e8 $151.80
+ e8a7204939bd995e0343c42de4366ad4fb95fe4d $-68.03
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-202.89
+
+2003/02/17 * fa73d67b17a393d9db8c96a9f3ec222804fe0fda
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $132.77
+ 4907823cffe667ad9decdcdd3a4780c15485c6ea
+
+2003/02/17 * 0f4b0afecf3d935e7bc810e1e0920cc8ee6f15ec
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $10.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/17 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 6.218000 EEEEE
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.00
+
+2003/02/17 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 20.020000 AAAAA
+ c56a21d23a6535184e7152ee138c28974f14280c $-360.01
+
+2003/02/17 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 8.803000 GGGGG
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.02
+
+2003/02/19 * 0f4b0afecf3d935e7bc810e1e0920cc8ee6f15ec
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $23.25
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/19 * 353483ad2a505c5f08dc1dc306993f394602c536
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $13.95
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/19 * 00115450eb0f8723f959072daa56a87a9aeddfee
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.83
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/19 * (102) bfe57c24b1164278d38739f81ca886131f8786aa
+ 2ff50cab09d039eaa717cac29cf2759eb39a007d $1,500.00
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78
+
+2003/02/20 * e65f77390d2ff7c7040d6fed1a6b62d5ba027748
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $274.31
+ af0628973ff35bd62ddb048fa41dd8d83c1c46fe
+
+2003/02/23 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-101.50
+
+2003/02/23 * e4811328450a9391ead85ddbcf2f25cda2e4ae2a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.16
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/24 * 288db0acb7096d8b553f3c77c9ef888a6e8ac5df
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $42.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/25 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.40
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/25 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $1,811.52
+ 15d4990b82d33262ff733b3e6539d66a0445c193 $600.02
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $539.70
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $245.80
+ a64166a90252d444071c62e9e0746ce6e83234b6 $57.48
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $97.15
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $48.46
+ c56a21d23a6535184e7152ee138c28974f14280c $600.02
+ (845ac5d9910830a5764c934bf791195b0fcd91f4) $114.00
+ 39189083b8637c7fff89e6bcf808790861417796 $-4,000.15
+
+2003/02/25 * 91361769cb74ddd9f9fc545ca4f1bc4e4d7d7212
+ c56a21d23a6535184e7152ee138c28974f14280c $120.01
+ 775a73f9b8633e396be7cfd03b6a46f07b47c5ef
+
+2003/02/26 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $0.39
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/02/26 * d66f20839763a4d86071659cdcbebaa6020203c3
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $10.35
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/26 * f159c0ab1d78ac3ddcd8264eed66b66516c7dd09
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.86
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/02/27 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 8.846000 GGGGG
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.02
+
+2003/02/27 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $167.36
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/02/27 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 20.050000 AAAAA
+ c56a21d23a6535184e7152ee138c28974f14280c $-360.01
+
+2003/02/27 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 6.276000 EEEEE
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.00
+
+2003/02/27 * dc53165e7620d16c1e26d61168889930b913ec30
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $1.53
+ e8a7204939bd995e0343c42de4366ad4fb95fe4d
+
+2003/02/28 * 1e5b455c3e91eb68f0f5e2505fa17afee84b96bc
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $2.70
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/02/28 * 5a146cb991ecea075a567f997ef95edad7fc3a24
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $7.57
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/02/28 * db16aa488f49561098cd08c4749d94256c733b64
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $450.00
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a
+
+2003/02/28 * 32fcd74c867c3ddbff9b8d38e8294d6727b1f3a2
+ e5dfa7a292da1dd185fc7c6dd2402ec582a15f37 $20.00
+ 88671479b5cf1fbd5df40139835b336f10e4c7a1
+
+2003/02/28 * 69f2e19499724e3daa9e84f5c1a4142cfe98889c
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $340.77
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/02/28 * 20bc87fd47b41f9abf6815df7496e90345f7ed37
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $32.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/02/28 * ab77b70037475007e0bf5fb4a3bbb53e817f64dd
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $7.78
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/01 * (2114) 74f61fee296e715055dc0f5ae30804ae450fb7dc
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $4,500.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/01 * 619cbfd21d72639f985324a9306696ce1262f3f6
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $5,079.15
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728
+
+2003/03/01 * 0760a28df0204fe7687476a3d0692abea12019d0
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $400.00
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb
+
+2003/03/01 * 5e5a42f9d5d96e9a5ce1bf6453a882644fa84c0b
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $2.02
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb
+
+2003/03/01 * 48227adff9f10cd94a570d7c9b7f6fe62cb6f4cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.45
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/01 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.85
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-31.85
+
+2003/03/01 * (2113) d1704e602da55041cc9c5f83a1076b1551c1225a
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a $450.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/02 * 2597cd5f96b6970b831a4f56c3c99335f549fb19
+ 9e67321982e83628563e8a2b396325aa18283ba5 $42.98
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/02 * b007369e15aba78cb6075310da96b854f5448a3a
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $1.93
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/02 * 63d0a265712c9c53d03cd1bde96c16ea9b114b06
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.05
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $10.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-22.05
+
+2003/03/03 * (2115) a4c1053a2870f13b1bfdd38db80b5d72acfba4d2
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $9.80
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/03 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.37
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/03 * 856c722d0a5c00b903ab4d7c2f93505edb13bb93
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.24
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/03 * b4fc2e8df9487473dcd996b2f84a238f6d20410b
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $10.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/03/04 * ab514b97e8f008682b50e6908a80a3fb024f8d82
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $66.33
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/04 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $28.43
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/04 * 0a104d94003cbb20ed0d8d2d014b5af21eed594f
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $35.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/05 * 2ad323f9a17e92818c9ca3626175803d8e6eb1df
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $4.38
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $6.78
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.24
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-13.40
+
+2003/03/05 * 504c6c141d7ed2aa8a8a8786be2225c39cee7a0f
+ 88671479b5cf1fbd5df40139835b336f10e4c7a1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/05 * a95c40f310c47178537882d69dcfe6b8b1dcc080
+ 9e67321982e83628563e8a2b396325aa18283ba5 $12.91
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/06 * 184d579b7e3f0d3158394da939e1fa3e9ec82df6
+ c0226fafdf9e6711ac9121cf263e2d50791859cb 3.729 CCCCC
+ e8a7204939bd995e0343c42de4366ad4fb95fe4d $-60.75
+
+2003/03/06 * 184d579b7e3f0d3158394da939e1fa3e9ec82df6
+ 7826c9ce60ae644a02466043232f592994802448 0.303 CCCCC
+ e8a7204939bd995e0343c42de4366ad4fb95fe4d $-4.94
+
+2003/03/07 * 9683fba84d910707cd96a7afcc0ddbc0162ae030
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.04
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/07 * 299eb28835cafffe80dbb8398c478bd6b35b34bf
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/09 * 0b4f388e2291d712032d94565e5bb1d10ecdc240
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/10 * 299eb28835cafffe80dbb8398c478bd6b35b34bf
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/11 * (2116) fa73d67b17a393d9db8c96a9f3ec222804fe0fda
+ 4907823cffe667ad9decdcdd3a4780c15485c6ea $96.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/12 * 9683fba84d910707cd96a7afcc0ddbc0162ae030
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.66
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/12 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.72
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-31.72
+
+2003/03/12 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $1,832.04
+ 15d4990b82d33262ff733b3e6539d66a0445c193 $600.02
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $548.42
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $247.01
+ a64166a90252d444071c62e9e0746ce6e83234b6 $57.77
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $98.72
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $16.15
+ c56a21d23a6535184e7152ee138c28974f14280c $600.02
+ (845ac5d9910830a5764c934bf791195b0fcd91f4) $114.00
+ 39189083b8637c7fff89e6bcf808790861417796 $-4,000.15
+
+2003/03/12 * 91361769cb74ddd9f9fc545ca4f1bc4e4d7d7212
+ c56a21d23a6535184e7152ee138c28974f14280c $120.01
+ 775a73f9b8633e396be7cfd03b6a46f07b47c5ef
+
+2003/03/12 * f94418bf56f6656f43bac8f2b9bf4ce940614f44
+ 9e67321982e83628563e8a2b396325aa18283ba5 $64.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/13 * (2117) 9d2e018cb90d72f2e27099e6771f33a7821b755a
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $9.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/13 * 63d0a265712c9c53d03cd1bde96c16ea9b114b06
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/14 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.36
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-53.36
+
+2003/03/14 * c78af9d477526fdbee1fe52fe1864bb6b7ab6d80
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $25.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/03/15 * 6c602e796082c3846297f7301fa0702f031a1647
+ f2580c2fa4873496427487e068658993bbf70894 $5.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/03/16 * b5a53b07e5ff84d945366dde1a100710e7bc2c2c
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/03/17 * f50bc0cf6300861a90dc5b29443cd614a09ffd88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $84.81
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/17 * 48227adff9f10cd94a570d7c9b7f6fe62cb6f4cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.45
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/17 * efccd2eb4dbdc2e2f6c7502eeab7816e686cbc8f
+ f2580c2fa4873496427487e068658993bbf70894 $3.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/03/18 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 6.038000 EEEEE
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.00
+
+2003/03/18 * fa39c23bd7d06b52f53d88060f6522ed961cc7e8
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.28
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/18 * fa39c23bd7d06b52f53d88060f6522ed961cc7e8
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $24.05
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/18 * fa73d67b17a393d9db8c96a9f3ec222804fe0fda
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $96.00
+ 4907823cffe667ad9decdcdd3a4780c15485c6ea
+
+2003/03/18 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 19.530000 AAAAA
+ c56a21d23a6535184e7152ee138c28974f14280c $-360.01
+
+2003/03/18 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 8.452000 GGGGG
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.02
+
+2003/03/21 * 6c602e796082c3846297f7301fa0702f031a1647
+ f2580c2fa4873496427487e068658993bbf70894 $8.25
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/03/21 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.07
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/21 * ab77b70037475007e0bf5fb4a3bbb53e817f64dd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.48
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/22 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.58
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-23.58
+
+2003/03/23 * 856c722d0a5c00b903ab4d7c2f93505edb13bb93
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.42
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/23 * 405295e72fc5fb41cb97a68a217108b08b4e045e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.28
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/24 * (104) cbf3dd2fe54446a3318e1632bc46a8ce5d491c07
+ 2ff50cab09d039eaa717cac29cf2759eb39a007d $10,000.00
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78
+
+2003/03/24 * c5e1c75940ae9c61c63e88e2ea2ea0ddc267e80d
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/25 * 66686066ebe4e49d4e972927e6b74b60b35f31b1
+ f0d45665b22d0562833aa3bf373c5b15640d833e $32.28
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/03/26 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $7,745.85
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $548.42
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $247.79
+ a64166a90252d444071c62e9e0746ce6e83234b6 $57.95
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $98.72
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $16.15
+ c56a21d23a6535184e7152ee138c28974f14280c $600.02
+ (845ac5d9910830a5764c934bf791195b0fcd91f4) $114.00
+ 39189083b8637c7fff89e6bcf808790861417796 $-4,000.15
+ 15d4990b82d33262ff733b3e6539d66a0445c193 $-5,314.75
+
+2003/03/26 * 91361769cb74ddd9f9fc545ca4f1bc4e4d7d7212
+ c56a21d23a6535184e7152ee138c28974f14280c $120.01
+ 775a73f9b8633e396be7cfd03b6a46f07b47c5ef
+
+2003/03/26 * 2b49ac1d006167806bc42ce9aec3e021b191e471
+ f0d45665b22d0562833aa3bf373c5b15640d833e $21.95
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/26 * 2a6badc29da609a5213520e707f23937f6868ea3
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $50,000.00
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78
+
+2003/03/27 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.21
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/27 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 6.110000 EEEEE
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.00
+
+2003/03/27 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 19.620000 AAAAA
+ c56a21d23a6535184e7152ee138c28974f14280c $-360.01
+
+2003/03/27 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 8.464000 GGGGG
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.02
+
+2003/03/27 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $0.28
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/03/27 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/27 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.98
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/27 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.46
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-29.46
+
+2003/03/28 * 6f5760cc33ed56ddc9a6400b6af23a1a6ee2ccf2
+ f2580c2fa4873496427487e068658993bbf70894 $8.25
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/03/28 * 2d298800f1e4be0638155d9fe2170eba13557611
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/03/30 * a0348dae1e8e55995eb3140e80c411954008c1b0
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.27
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/30 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $170.64
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/03/30 * dc53165e7620d16c1e26d61168889930b913ec30
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $1.76
+ e8a7204939bd995e0343c42de4366ad4fb95fe4d
+
+2003/03/31 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.64
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $10.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-20.64
+
+2003/03/31 * db16aa488f49561098cd08c4749d94256c733b64
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $450.00
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a
+
+2003/03/31 * 32fcd74c867c3ddbff9b8d38e8294d6727b1f3a2
+ e5dfa7a292da1dd185fc7c6dd2402ec582a15f37 $20.00
+ 88671479b5cf1fbd5df40139835b336f10e4c7a1
+
+2003/03/31 * (2119) 19ebae82957ef58483f1354c5b179fcdf5394fcd
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $250.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/31 * (2118) d1704e602da55041cc9c5f83a1076b1551c1225a
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a $450.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/03/31 * 8f2a9369c196f88970181565a81aab1d8816b126
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.41
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $21.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-32.41
+
+2003/04/01 * cbb4cc49824bf79827cde838e005848027ca0a38
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $50,005.00
+ fc0e191163be4d1966e3c51b1635401f9e82a807
+
+2003/04/01 * 893268b30e0a141b8640052be1e47d440cbd51d0
+ 5ea6ff037c50e85215211c1c1a25eebf6014611e $49.98
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/01 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $36.62
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-56.62
+
+2003/04/01 * fa39c23bd7d06b52f53d88060f6522ed961cc7e8
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $26.22
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/04/02 * 9683fba84d910707cd96a7afcc0ddbc0162ae030
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.66
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/02 * a4c1053a2870f13b1bfdd38db80b5d72acfba4d2
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $19.60
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/04 * 8f2a9369c196f88970181565a81aab1d8816b126
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.52
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/04 * cc9de4beb764c10c43d0de61ae9a5235b049c860
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/05 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.38
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/05 * 299eb28835cafffe80dbb8398c478bd6b35b34bf
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/05 * 504c6c141d7ed2aa8a8a8786be2225c39cee7a0f
+ 88671479b5cf1fbd5df40139835b336f10e4c7a1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/04/05 * 0f4b0afecf3d935e7bc810e1e0920cc8ee6f15ec
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $3.43
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-23.43
+
+2003/04/07 * be95ab7efd9f203a652c73b9031c74106f994112
+ 181884ada86d2c3e7511e3ef3830fcf9f75b1421 $2.67
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/07 * 14a4b0336015e7b388359c2399c2d96845f3225e
+ 181884ada86d2c3e7511e3ef3830fcf9f75b1421 $2.13
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/07 * 14a4b0336015e7b388359c2399c2d96845f3225e
+ ac98afc9665076c4a5755414b1a6790587f3f61d $97.92
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/07 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $25.84
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-45.84
+
+2003/04/07 * (2120) 8ca15484a6a50617febf823f3fa1c9e7038688ee
+ 81234cef338d70f98ca31d7d2ea1e53e65a4f4a6 $5.34
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/04/08 * 4ab92ebbd07dc710dd4fd5bd35a51d063b8b192e
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $32.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/08 * af636338204eb20a819cb1da004e0332d82b995e
+ 7134396063db3d3d81defdb1a2c68ee1383d199f $11.84
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/08 * 86de503686d1c3ce821d65d3013305099b1dba57
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $19.37
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/08 * fa39c23bd7d06b52f53d88060f6522ed961cc7e8
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $26.93
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/08 * 606ec6e9bd8a8ff2ad14e5fade3f264471e82251
+ 628072f9bfc87daeb5e0144ef2090ef8057935e8 $98.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/08 * (2121) bfe57c24b1164278d38739f81ca886131f8786aa
+ 2ff50cab09d039eaa717cac29cf2759eb39a007d $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/04/09 * b5a53b07e5ff84d945366dde1a100710e7bc2c2c
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.00
+ f0d45665b22d0562833aa3bf373c5b15640d833e
+
+2003/04/09 * 0bdfa162041573731f35ed9a115cebcceba07a68
+ 592a60e960113a755f70f9b58ef7a97b5aca14dc $64.45
+ f0d45665b22d0562833aa3bf373c5b15640d833e $32.22
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-64.45
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $-32.22
+
+2003/04/09 * 902328fdb92afdd6f4228b37cf9330a5560a7ec9
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $5.34
+ 81234cef338d70f98ca31d7d2ea1e53e65a4f4a6
+
+2003/04/10 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $2,432.06
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $548.42
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $247.01
+ a64166a90252d444071c62e9e0746ce6e83234b6 $57.77
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $98.72
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $16.15
+ c56a21d23a6535184e7152ee138c28974f14280c $600.02
+ (845ac5d9910830a5764c934bf791195b0fcd91f4) $114.00
+ 39189083b8637c7fff89e6bcf808790861417796 $-4,000.15
+
+2003/04/10 * 03642d4c8cfd39cbe8e1bbce3179a0ca53935e30
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $104.04
+ f0d45665b22d0562833aa3bf373c5b15640d833e
+
+2003/04/10 * (2122) e1bc40eb9e5cdab590fbf9e1075d4e3e219ad073
+ c0226fafdf9e6711ac9121cf263e2d50791859cb 173.820 CCCCC
+ (845ac5d9910830a5764c934bf791195b0fcd91f4) $570.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-3,000.00
+
+2003/04/10 * 0fb419d273cdd0cfe9825e94f91c2058e99c1f7a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/10 * 90b08ef8dda426f62ad84b8181275f0494c1d835
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/11 * 856c722d0a5c00b903ab4d7c2f93505edb13bb93
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.30
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/12 * b5cd9e578b070853a53006aabc7b4ac08f2a5634
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/13 * 4d565ed871c3d07f2878d73e18576ceb83f8700b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.89
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/13 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/14 * 8a3f780d3b3b0968084ca4b17c81945bbf1313a1
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $47.75
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb
+
+2003/04/14 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $60.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-61.50
+
+2003/04/14 * 7b17de2b0f498812aae7790797cd9cfd6744497d
+ f2580c2fa4873496427487e068658993bbf70894 $8.25
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/14 * 95124b1c42080a5a8ca490558a5ecff9254976fc
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.95
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $10.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-31.95
+
+2003/04/14 * 4f36cda4f67b75a4ef1e867a0a51313233c04879
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $2,292.00
+ f0d45665b22d0562833aa3bf373c5b15640d833e $1,146.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-2,292.00
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $-1,146.00
+
+2003/04/14 * 2a9649e01b659d9afcee414f35ac009fb43eed0c
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $111.00
+ f0d45665b22d0562833aa3bf373c5b15640d833e $55.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-111.00
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $-55.50
+
+2003/04/14 * 91361769cb74ddd9f9fc545ca4f1bc4e4d7d7212
+ c56a21d23a6535184e7152ee138c28974f14280c $120.01
+ 775a73f9b8633e396be7cfd03b6a46f07b47c5ef
+
+2003/04/15 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 19.150000 AAAAA
+ c56a21d23a6535184e7152ee138c28974f14280c $-360.01
+
+2003/04/15 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 8.198000 GGGGG
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.02
+
+2003/04/15 * 1d3c457cbe3e35739086346e0a4048653efa42e7
+ c56a21d23a6535184e7152ee138c28974f14280c 5.920000 EEEEE
+ c56a21d23a6535184e7152ee138c28974f14280c $-180.00
+
+2003/04/15 * 9fca7b8d5eb6cc9b0272edc33d05a50c77fa5589
+ f2580c2fa4873496427487e068658993bbf70894 $8.25
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/15 * e4811328450a9391ead85ddbcf2f25cda2e4ae2a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.43
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/16 * f50bc0cf6300861a90dc5b29443cd614a09ffd88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $705.77
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/04/16 * 9ff6a9a7bab441b118a9019bf2d71b383d45e1c2
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $29.81
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/17 * a9b1ff0e867b716c67d5fde2a4debeae33680767
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/18 * d32081745b974201fd00fd7a51593397f65e90fb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $43.30
+ a70b28cd2c82422e6d011d08a07354b598647e21 $25.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-68.30
+
+2003/04/18 * c93854544737d531f50beb467d31d8d475d3689f
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $412.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/19 * 2581e49665bf2c87bd92626e8d57b5c36bc81824
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.10
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/19 * fa73d67b17a393d9db8c96a9f3ec222804fe0fda
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $54.49
+ 4907823cffe667ad9decdcdd3a4780c15485c6ea
+
+2003/04/20 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.63
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/20 * 69f2e19499724e3daa9e84f5c1a4142cfe98889c
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $394.09
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/20 * d2c1a43ad8690a29876c057c40b1ee57985ea0be
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.40
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/21 * 856c722d0a5c00b903ab4d7c2f93505edb13bb93
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.23
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/21 * 20bc87fd47b41f9abf6815df7496e90345f7ed37
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728 $36.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/21 * 299eb28835cafffe80dbb8398c478bd6b35b34bf
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.65
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/21 * e31437bf8090bfa5241296d0eafdb3ff965dd7ad
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $156.09
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/22 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.82
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/22 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.26
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-37.26
+
+2003/04/22 * 58c0f13307f8ae95dae0f4d9c56b7237bfef70d6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.49
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/04/23 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/24 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.84
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/24 * 183f36d6f93a6c3a9776e73e8043fac90691688e
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $2.27
+ f0d45665b22d0562833aa3bf373c5b15640d833e
+
+2003/04/25 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $3,545.27
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $756.84
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $297.97
+ a64166a90252d444071c62e9e0746ce6e83234b6 $69.69
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $136.23
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $9.69
+ 39189083b8637c7fff89e6bcf808790861417796 $-4,815.69
+
+2003/04/25 * (2123) 35b7ad4a355641a58d7ef29cce5ce8dadc550d35
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $30.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/04/26 * 3e19ef28eacde8d6883cff95fa747530e063b41f
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $22.07
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/27 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.30
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/28 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.09
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/04/28 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $40.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-41.50
+
+2003/04/28 * 91c59df073c8abd416047acbac4f38dd4834d955
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.94
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/28 * 0ab795183acd4eb0c332210e6923567f143d89c2
+ 81e80d3e70928f8f87ca90648f81a63efe7625f5 $40.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/29 * 2ad323f9a17e92818c9ca3626175803d8e6eb1df
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $10.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/29 * de358b30b4412964cb0ca6d32d8abff18ecbf961
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $1.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/29 * de358b30b4412964cb0ca6d32d8abff18ecbf961
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $9.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/29 * 2ad323f9a17e92818c9ca3626175803d8e6eb1df
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.39
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/30 * dc53165e7620d16c1e26d61168889930b913ec30
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $0.84
+ e8a7204939bd995e0343c42de4366ad4fb95fe4d
+
+2003/04/30 * 51520e9e33ca70311b1deeaa3f3b8d85e5affea8
+ 48bf83c24e711997303a05a83ee60500102f2976 $848.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/30 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.53
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/30 * c724d9c91df5cb3bd4441a2cd9e15676c61555f7
+ 5ea6ff037c50e85215211c1c1a25eebf6014611e $81.92
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/04/30 * d0ce056a8a02b5d15225f39beb931bde9179fec5
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.60
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/30 * 97a7a570c8ede9be3bb8ca6edb1ee14e1012c595
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.80
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/04/30 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $162.00
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/05/01 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.16
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/01 * db16aa488f49561098cd08c4749d94256c733b64
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $450.00
+ 11c48bb7aa6231a23d96299904885620d9fb3b1a
+
+2003/05/02 * 6c602e796082c3846297f7301fa0702f031a1647
+ f2580c2fa4873496427487e068658993bbf70894 $8.75
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/05/03 * 2ad323f9a17e92818c9ca3626175803d8e6eb1df
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.48
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/03 * cc9de4beb764c10c43d0de61ae9a5235b049c860
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/05/05 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.96
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-24.96
+
+2003/05/05 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.28
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/06 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/06 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $25.53
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/06 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.27
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/07 * 902328fdb92afdd6f4228b37cf9330a5560a7ec9
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $12.27
+ 81234cef338d70f98ca31d7d2ea1e53e65a4f4a6
+
+2003/05/07 * 39ccba9779f59020ae45a9df08864376a1011b80
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.78
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/08 * (2124) fa73d67b17a393d9db8c96a9f3ec222804fe0fda
+ 4907823cffe667ad9decdcdd3a4780c15485c6ea $54.49
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/05/08 * (2125) 8ca15484a6a50617febf823f3fa1c9e7038688ee
+ 81234cef338d70f98ca31d7d2ea1e53e65a4f4a6 $12.27
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/05/09 * 04ff4313e11dca88fb1707316329ff143f8f78c2
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.02
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/09 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ 1a8916d9798e34d59fd604a7ebde9d5054c84b70 $17.90
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/09 * 39ccba9779f59020ae45a9df08864376a1011b80
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.21
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/09 * 353483ad2a505c5f08dc1dc306993f394602c536
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $14.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/09 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.18
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-39.18
+
+2003/05/11 * f25484d2cb3be21faecbe8b4d73dfd1f71c81415
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $4.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/13 * 75efa04022957aea8efebc48dd0bd95b636049c1
+ 71c454369dde750a77c84ae295ddb94bfc43ec16 $8.25
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/05/14 * 30ae3121b82a0a4f50abfc80fc5ea66cfeb184ce
+ f2580c2fa4873496427487e068658993bbf70894 $3.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/05/14 * 8f2a9369c196f88970181565a81aab1d8816b126
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/14 * 47bd01914364608da003849c18f7774a4b9c5309
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/14 * 299eb28835cafffe80dbb8398c478bd6b35b34bf
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/15 * 6f5760cc33ed56ddc9a6400b6af23a1a6ee2ccf2
+ f2580c2fa4873496427487e068658993bbf70894 $8.25
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/05/15 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.86
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-24.86
+
+2003/05/15 * e31437bf8090bfa5241296d0eafdb3ff965dd7ad
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $37.09
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/16 * f50bc0cf6300861a90dc5b29443cd614a09ffd88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $633.26
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/05/16 * d0ce056a8a02b5d15225f39beb931bde9179fec5
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.20
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/16 * e313acc89483a750c6d21ef204fe7913fcb2db7c
+ 5ea6ff037c50e85215211c1c1a25eebf6014611e $144.34
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/17 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.98
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/17 * 0fb419d273cdd0cfe9825e94f91c2058e99c1f7a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.70
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/17 * 47bd01914364608da003849c18f7774a4b9c5309
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $1.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/17 * (2126) bfe57c24b1164278d38739f81ca886131f8786aa
+ 2ff50cab09d039eaa717cac29cf2759eb39a007d $25.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/05/18 * 6e1dffe991650653e71c21ac5c534f5bbb159f18
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $23.69
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/18 * 3188e18375b5076df0c9d2dffc7de069ff2bf422
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.37
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/19 * 47bd01914364608da003849c18f7774a4b9c5309
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.78
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/19 * (2127) 3561bec15d2b90f18a703a6503e4b02faa408fdd
+ e940525b878f1783a30bf0cd9c040f6d27e0568c $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/05/20 * e31437bf8090bfa5241296d0eafdb3ff965dd7ad
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $7.52
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/20 * cf210ef5c8d4334c58a16819fdf1e249db004809
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.51
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/20 * cf210ef5c8d4334c58a16819fdf1e249db004809
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.11
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/20 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $17.61
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/20 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.59
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/21 * 56d273aa71c0343175835d0446e4227e8281b5e3
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/05/21 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/22 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-101.00
+
+2003/05/22 * 6e1dffe991650653e71c21ac5c534f5bbb159f18
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $22.03
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/22 * b883e3aa0affdec26d5881142b07325aafadec89
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $3.77
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/23 * 710989ca32db257189a0fa0ce2cbd146542cd53b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.79
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/23 * 4ffc4349510313ea639fc1e50d7e156c456cdb84
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/05/24 * 478b8cf87b83049bacb3b8d81693a1a9ee1a2af9
+ f2580c2fa4873496427487e068658993bbf70894 $5.76
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $5.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-10.76
+
+2003/05/24 * (2128) bea8d5e2678e516790a1d65f5c22875c1ee81f09
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $60.50
+ f2580c2fa4873496427487e068658993bbf70894 $9.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-70.00
+
+2003/05/24 * 710989ca32db257189a0fa0ce2cbd146542cd53b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.03
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/24 * cdbd6445b409d06d3bbeee9ad27c1d535ba7f6df
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.77
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/25 * be70ff73a1b22f302bc8af7bd32ee4273f2d8636
+ f2580c2fa4873496427487e068658993bbf70894 $6.25
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/05/25 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/25 * d2667e42a8beac84d6f95887ab807a947a425d67
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.66
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/26 * f9c0127a2f9298b71d7139c40fcdfd3a8ca7a670
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $25.00
+ a70b28cd2c82422e6d011d08a07354b598647e21
+
+2003/05/26 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $1,545.11
+ 677639d3e48c3ac2413f12c1a3e6b67525e09009 $192.35
+ 4fd4e6978513bf18a906891e8e8c4b307ae3565e $118.97
+ a64166a90252d444071c62e9e0746ce6e83234b6 $27.82
+ 37beb706a7535f3da1e5f5411c5c15bd4115a4bb $34.62
+ 39189083b8637c7fff89e6bcf808790861417796 $-1,918.87
+
+2003/05/26 * 710989ca32db257189a0fa0ce2cbd146542cd53b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.98
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $4.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-6.98
+
+2003/05/26 * f1ba777d5cb86fe74056909a67c8d1ef5da7f8a9
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/05/29 * 1179ed4613d2431a8e74caafcc139d3a02926714
+ d7e87874854606f9910166abbf7e603606f0010c $21.34
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/29 * 11208e4d2c3ad4fdaab5633e552930c53992fac3
+ 192c6a87c9e21761ef867c199811018469d948eb $53.35
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/05/30 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $178.45
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/05/31 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $170.50
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/05/31 * 041cf7433e58e494cb7f0c7b5e03e8171366e1b4
+ 192c6a87c9e21761ef867c199811018469d948eb $847.71
+ b4b664a91f882e715c97f7eb9069a7d79797f07b $160.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-1,007.71
+
+2003/06/02 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $179.97
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/03 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $178.84
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/04 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $178.24
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/05 * c0d1a562583cec8ebcfeea3d086f9d07047efce2
+ 192c6a87c9e21761ef867c199811018469d948eb $27.15
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/06/07 * d250dcaaf8df1331e9e62e28c909f3ae9928b6d0
+ d7e87874854606f9910166abbf7e603606f0010c $92.89
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/06/09 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $201.63
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/11 * 9126b4d2ae43038749feb7efd0d929f923cb2ccc
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $89.17
+ 904eafc4a3d3e7ee665de39f7baa66d9785b3c98
+
+2003/06/12 * 041cf7433e58e494cb7f0c7b5e03e8171366e1b4
+ 48bf83c24e711997303a05a83ee60500102f2976 $78.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/06/15 * e31437bf8090bfa5241296d0eafdb3ff965dd7ad
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $11.75
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/06/16 * 041cf7433e58e494cb7f0c7b5e03e8171366e1b4
+ 48bf83c24e711997303a05a83ee60500102f2976 $44.36
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/06/16 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $2,345.10
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/16 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $179.73
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/19 * cbb4cc49824bf79827cde838e005848027ca0a38
+ c56a21d23a6535184e7152ee138c28974f14280c 331.296869 LMVTX @ $53.6599999999999999998612221219
+ c56a21d23a6535184e7152ee138c28974f14280c -523.942988 EEEEE @ $33.9299999999999999998438748872
+ c56a21d23a6535184e7152ee138c28974f14280c 55.981364 LMVTX @ $53.6599999999999999998612221219
+ c56a21d23a6535184e7152ee138c28974f14280c -88.534054 EEEEE @ $33.9299999999999999998438748872
+
+2003/06/23 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $177.81
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/25 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $175.55
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/25 * f78a1b5ad54150ad91ac6f69b1836ab8a8c4f59c
+ 48bf83c24e711997303a05a83ee60500102f2976 $13.07
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/06/26 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $58.23
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/27 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $186.58
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/30 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $172.81
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/30 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $172.81
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/06/30 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $165.27
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/07/01 * (103) cbb4cc49824bf79827cde838e005848027ca0a38
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $10,000.00
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78
+
+2003/07/03 * 58d902c2682a604912762fccf312f03da2581284
+ d7e87874854606f9910166abbf7e603606f0010c $40.48
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/07/07 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $174.78
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/07 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $174.19
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/10 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $171.67
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/10 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $171.67
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/11 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $172.17
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/14 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $171.76
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/14 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $172.58
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/15 * e31437bf8090bfa5241296d0eafdb3ff965dd7ad
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $11.75
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/07/16 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $1,616.30
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/16 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $171.27
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/21 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $203.14
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/21 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $170.19
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/21 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $171.11
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/23 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $171.97
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/24 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $172.10
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/28 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $174.15
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/28 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $174.92
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/29 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $208.78
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/30 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $174.36
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/07/31 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $158.25
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/08/04 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $202.43
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/08/04 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $202.43
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/08/06 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $205.56
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/08/06 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $172.35
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/08/08 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $205.78
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/08/11 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $205.53
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/08/11 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $171.82
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/08/13 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $205.16
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/08/14 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $170.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/08/15 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $109.66
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/08/17 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $25.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/17 * 344a788f45ac818f83648b6c76a1538282c1fcfc
+ d7e87874854606f9910166abbf7e603606f0010c $4,224.52
+ 192c6a87c9e21761ef867c199811018469d948eb $2,574.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $-6,798.52
+
+2003/08/17 * 5e5ac02782568145cf77bb0dbf15d2b37174f54f
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/08/18 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $200.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-201.50
+
+2003/08/18 * a68640eec7fa0e2090324c1f649ae961549fe98e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/18 * e31437bf8090bfa5241296d0eafdb3ff965dd7ad
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $11.76
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/19 * 3837f7cdd2718dc7c9adb5697841d95b3b48e412
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.87
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/08/19 * 710989ca32db257189a0fa0ce2cbd146542cd53b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.65
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/20 * 710989ca32db257189a0fa0ce2cbd146542cd53b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $22.90
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/20 * c6f1f561f070c16cc7a1d989b24fd466e041f909
+ f2580c2fa4873496427487e068658993bbf70894 $10.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/08/22 * 1d4fdf992a2f21724715605e9157c282de68924d
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $16.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/22 * 710989ca32db257189a0fa0ce2cbd146542cd53b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/23 * 91c59df073c8abd416047acbac4f38dd4834d955
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.56
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/08/23 * 353483ad2a505c5f08dc1dc306993f394602c536
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $23.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/23 * 61ad50a9b9189cc3cf1874568e35e7901ff4c982
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $48.51
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/24 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.93
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/25 * 0fb419d273cdd0cfe9825e94f91c2058e99c1f7a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.64
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/28 * 2470dca59588f4db61caa65758dc3be6e848d811
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.70
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/29 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.67
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/29 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $31.56
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/29 * 09c0b607d75b45cfe399ef37683597e6010ad3b4
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.65
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/30 * 0664566aef3c0cf8fe661bc4bb62e31e4e8fd435
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $9.80
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/08/31 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $21.69
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/31 * 39ccba9779f59020ae45a9df08864376a1011b80
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.01
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/08/31 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $119.98
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/09/01 * 63d0a265712c9c53d03cd1bde96c16ea9b114b06
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.86
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/02 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.35
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/02 * 7994a463ade0f972bf1bb59ac236e37b08bfc4d7
+ 628072f9bfc87daeb5e0144ef2090ef8057935e8 $202.39
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/09/03 * cdbd6445b409d06d3bbeee9ad27c1d535ba7f6df
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $3.21
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/03 * 856c722d0a5c00b903ab4d7c2f93505edb13bb93
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.36
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/04 * 8719b3bde8326bcc3e3dcc12c2ffb7fea691b1cc
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.29
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/05 * 15a05d714d00be0c9802f0ec604d52966a3ceb10
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.91
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/05 * 4c1b9c1def0a6e56d3d22891a22c7e171d9133f0
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.90
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/06 * 04ff4313e11dca88fb1707316329ff143f8f78c2
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.03
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/06 * 478b8cf87b83049bacb3b8d81693a1a9ee1a2af9
+ f2580c2fa4873496427487e068658993bbf70894 $10.33
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/06 * 39ccba9779f59020ae45a9df08864376a1011b80
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.45
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/07 * 685f23bc5eb93fc982292395e8c03a40670ce3ec
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.82
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/07 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $1.89
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/09/07 * a06a7623ea4babf483fa88f403655cc42be3fe14
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.45
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/08 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $200.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/09/08 * 2470dca59588f4db61caa65758dc3be6e848d811
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.59
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/08 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $16.96
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/08 * f1a1dcb303695a9107bef9686ec91b4fb3f2e19f
+ 10cab4f7105feed78ca34f97ba79d013cb8e28f4 $15.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/08 * f1a1dcb303695a9107bef9686ec91b4fb3f2e19f
+ 10cab4f7105feed78ca34f97ba79d013cb8e28f4 $15.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/08 * 6f5760cc33ed56ddc9a6400b6af23a1a6ee2ccf2
+ f2580c2fa4873496427487e068658993bbf70894 $17.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/09/09 * 39ccba9779f59020ae45a9df08864376a1011b80
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.34
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/09 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $25.52
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/09 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.79
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/10 * 478b8cf87b83049bacb3b8d81693a1a9ee1a2af9
+ f2580c2fa4873496427487e068658993bbf70894 $4.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/10 * f1a1dcb303695a9107bef9686ec91b4fb3f2e19f
+ 10cab4f7105feed78ca34f97ba79d013cb8e28f4 $10.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/11 * cdbd6445b409d06d3bbeee9ad27c1d535ba7f6df
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.45
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/11 * f750981f288338dc2e2da75e826a63f54440d929
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.80
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/12 * 427dc6551f1155d59fceaabaeb34eafc400109b6
+ f2580c2fa4873496427487e068658993bbf70894 $7.75
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/09/12 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $28.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/13 * 6f5760cc33ed56ddc9a6400b6af23a1a6ee2ccf2
+ f2580c2fa4873496427487e068658993bbf70894 $5.25
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/09/13 * 48227adff9f10cd94a570d7c9b7f6fe62cb6f4cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.45
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/15 * 856c722d0a5c00b903ab4d7c2f93505edb13bb93
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.73
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/16 * 3e19ef28eacde8d6883cff95fa747530e063b41f
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $17.01
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/16 * 3e19ef28eacde8d6883cff95fa747530e063b41f
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.90
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/16 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $11.75
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/09/17 * 7c32c47523acc8ef0405a7554be36e6ddc02cb21
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $9.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/18 * 3a8df97eb4b7f9359d704a4eff1adec76a44f5e7
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/18 * d66f20839763a4d86071659cdcbebaa6020203c3
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $25.35
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/09/18 * 3a8df97eb4b7f9359d704a4eff1adec76a44f5e7
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $23.29
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/19 * eda08d7efcc9dc0b10d261c85f3e2861819a60ce
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/19 * dd68a4b38b001011fb067db32f136eb0a4790f95
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $31.54
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/20 * f159c0ab1d78ac3ddcd8264eed66b66516c7dd09
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.86
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/20 * 67892daef69b2043c22227601adcbfb25054ea39
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/21 * a1707a49d3dbd76e84fa94676f68c659af8133d1
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $246.75
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/21 * d2667e42a8beac84d6f95887ab807a947a425d67
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.73
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/22 * d08303b27dd02c246f06c8cf3969e3a04d54ea94
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $24.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/22 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.30
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/22 * 3e19ef28eacde8d6883cff95fa747530e063b41f
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.73
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/24 * 920f974dd8e6bbf94ef863cfbba66e67c347dc65
+ f2580c2fa4873496427487e068658993bbf70894 $10.00
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $-25.00
+
+2003/09/24 * 91c59df073c8abd416047acbac4f38dd4834d955
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.29
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/09/24 * ebd0c5f989f35ee5e746cc1ffeb823edee7846c3
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $25.18
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/24 * 95298d92d7000f1debf0ad06e7bd74c2af3823f4
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.39
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/25 * (2129) 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $30.00
+ b52415543ea21652cd42ab1cbd832ffe3ac46c18 $940.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-1,920.00
+
+2003/09/25 * (2130) 19f3c81bfcf220f767c442ed5722e3191d604a98
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $200.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-140.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $-60.00
+
+2003/09/26 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/26 * be95ab7efd9f203a652c73b9031c74106f994112
+ 181884ada86d2c3e7511e3ef3830fcf9f75b1421 $7.40
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/09/26 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $11.78
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.20
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-31.98
+
+2003/09/26 * 50ee198a36346bb0c8bba88eb7636ce18bd4faaa
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $21.70
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/26 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-101.50
+
+2003/09/26 * fafc3ee2608e739320f4cbe2db38fb45c30f64d0
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/26 * 61ad50a9b9189cc3cf1874568e35e7901ff4c982
+ 7134396063db3d3d81defdb1a2c68ee1383d199f $5.40
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/26 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.22
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/26 * fafc3ee2608e739320f4cbe2db38fb45c30f64d0
+ 7134396063db3d3d81defdb1a2c68ee1383d199f $59.52
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/27 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.88
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $10.67
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-16.55
+
+2003/09/27 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $4.28
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/27 * 5478fc25bca0ae185f2c2d36781fc1840ac0b42a
+ f2580c2fa4873496427487e068658993bbf70894 $9.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/09/28 * a946632db5acafcf73e541098cacb660c6dda9e0
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $16.65
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/09/28 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 71c454369dde750a77c84ae295ddb94bfc43ec16 $8.99
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $6.66
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-15.65
+
+2003/09/29 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/09/30 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $111.38
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/09/30 * 99f35cfe037ce7200aab33a50ae0151c73244548
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/09/30 * f7dfe4fbd5e0b9027298ac1a5543cc0f5c2a2a30
+ f1cd21cd287244422551d04963bc2cf4a5f30cde $7.03
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/09/30 * f7dfe4fbd5e0b9027298ac1a5543cc0f5c2a2a30
+ f1cd21cd287244422551d04963bc2cf4a5f30cde $129.88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/01 99f35cfe037ce7200aab33a50ae0151c73244548
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.25
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/02 * a52b087bf5b2c8dba6d050f3cb79d42ce89826ff
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $31.46
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/02 a52b087bf5b2c8dba6d050f3cb79d42ce89826ff
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/03 99f35cfe037ce7200aab33a50ae0151c73244548
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/03 * 06e1515d7acf1e9b3869e82b570fd55c60ed97c2
+ 5ea6ff037c50e85215211c1c1a25eebf6014611e $27.04
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/03 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-101.50
+
+2003/10/03 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/04 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $25.09
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/04 51055eddd536eaba10df20495173acfab1c6f52e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/04 * 1133a4e496a435e39ee41202eb07f46637ef5b62
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $17.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/04 * dfcde5b76512cd71d51002f76cc62cf9e25f0d77
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/04 * befeb39a3e027511ff64ff1d3b7232c6fe2da108
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $26.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/04 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.99
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $0.66
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-8.65
+
+2003/10/04 * b45923836563f437a6394be8f4fd035bf7145f8d
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $4,289.30
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/06 * d39973357f14216e757ef5839d4fc571e1a69abf
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.87
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/06 * abec79e51147db01996bcff0e1eb2fef39c1bb68
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $198.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/06 * befeb39a3e027511ff64ff1d3b7232c6fe2da108
+ a7cefcc26daa42c746631597e921d13810dd1e5d $57.19
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/07 4dab783e187b6ba8917a01e93ceb1580321395f9
+ 3e2706db92ca6bb952333fd028e582695910c01d $6.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/07 * 535e770a4622fe8e4aa42e54c99c859adc8e9f36
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/08 * 4331e9979566987b4e3c8e7868f918be5705df38
+ a7127d3fcaafa2eeaa5369ae245a4835a250d084 $39.95
+ 1237fd153ab3077a51de74b5e659441b7bf6ef01 $8.05
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-48.00
+
+2003/10/08 b5691b21f1b8e3bca1caee7269c873d9a93eb8e8
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/08 47d722f2ba03396fb8bbabf01fdbfc1cbfa6e7fe
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $20.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/14 * 2215b86d97712591977ef1bbffb35eb398e76624
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $56.48
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/14 c657a077d616bc8d5a7a82b2b1bf41292b4fe5b1
+ 3e2706db92ca6bb952333fd028e582695910c01d $17.25
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/15 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.03
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/15 * 96a3c221e59f05da813698be1262f09f791aaa42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.42
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/15 * 96a3c221e59f05da813698be1262f09f791aaa42
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $443.79
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/15 * c406fac5adce4abf7cd534369aa1ae3bd5360635
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $43.30
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/16 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $571.91
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/10/16 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $4.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/16 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.45
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/16 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.79
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-53.79
+
+2003/10/16 * 6cfe6d803407aca6e30527c8a26fc31f5a9f7944
+ a7cefcc26daa42c746631597e921d13810dd1e5d $79.20
+ a7cefcc26daa42c746631597e921d13810dd1e5d $118.80
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-198.00
+
+2003/10/17 99f35cfe037ce7200aab33a50ae0151c73244548
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/17 e59a2ab6add54c1cf14f7764f53e4a0fa82cd542
+ f2580c2fa4873496427487e068658993bbf70894 $9.75
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/18 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/18 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.97
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/19 * b422694a3e6330fa33f2996acb27cc83093c1cdf
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $19.43
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/19 * a7791c30537bb428e31775f1699cf2258acd4921
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $53.46
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/19 bdd0da1d8175aae2d2b23628e037210e17dfa259
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/20 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $40.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/10/20 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/20 9fca7b8d5eb6cc9b0272edc33d05a50c77fa5589
+ f2580c2fa4873496427487e068658993bbf70894 $5.75
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/20 * a52b087bf5b2c8dba6d050f3cb79d42ce89826ff
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $-5.00
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.98
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/21 99f35cfe037ce7200aab33a50ae0151c73244548
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/21 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/22 99f35cfe037ce7200aab33a50ae0151c73244548
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/22 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $1.98
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/22 * 3e19ef28eacde8d6883cff95fa747530e063b41f
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.53
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/22 * fafc3ee2608e739320f4cbe2db38fb45c30f64d0
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/22 * f7dfe4fbd5e0b9027298ac1a5543cc0f5c2a2a30
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $173.18
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/22 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.38
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/23 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/23 * eb318e3f91d44bd7994f1be909b79e937415eced
+ f2580c2fa4873496427487e068658993bbf70894 $4.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/24 * b45923836563f437a6394be8f4fd035bf7145f8d
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $139.64
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/24 * 45c2dbcd2131ea9530c2615d971be996790da2b4
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.30
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/25 * c7fa9b02553297834a21dc022d55dede1c98580c
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.73
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/26 * 619cbfd21d72639f985324a9306696ce1262f3f6
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $7,000.00
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78
+
+2003/10/26 * (2131) 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ d27230e86aebbd6883e399ba2e38f635de9738a2 $3.17
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/10/26 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $80.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-81.50
+
+2003/10/27 * (2132) 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/10/27 5478fc25bca0ae185f2c2d36781fc1840ac0b42a
+ f2580c2fa4873496427487e068658993bbf70894 $9.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/27 * 024c1ec682f0ba522659c8afbbb4948b8d212f8f
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.64
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/27 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $2.97
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/28 ab77b70037475007e0bf5fb4a3bbb53e817f64dd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/10/29 * 96a3c221e59f05da813698be1262f09f791aaa42
+ a7cefcc26daa42c746631597e921d13810dd1e5d $21.64
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/29 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.68
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/29 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.04
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/29 * 953388f315fdab9d0166aaa871ca84fc212af6fd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.93
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/30 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.15
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/30 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $4.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/30 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/31 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $112.00
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/10/31 * 6ed2ba8998c24c45c47b4a32078684e29ad113a4
+ 59284ef86feceb946c427aeb6c0badfeb415b446 $10.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/10/31 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $162.36
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/10/31 91c59df073c8abd416047acbac4f38dd4834d955
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.21
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/11/01 * 3e19ef28eacde8d6883cff95fa747530e063b41f
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $25.07
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/01 * 96e51d54e372ee3a69132305ed33b271d5414038
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $23.43
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/03 * a52b087bf5b2c8dba6d050f3cb79d42ce89826ff
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $37.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/03 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.81
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/04 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.14
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/04 * a52b087bf5b2c8dba6d050f3cb79d42ce89826ff
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $35.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/05 * b3dee3f782518ed1c60469f04f4fdca82e619534
+ f2580c2fa4873496427487e068658993bbf70894 $11.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $10.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-21.00
+
+2003/11/06 * (2133) 77d8308bb137226ac832a1e96ff81a6ae5a5d086
+ 59284ef86feceb946c427aeb6c0badfeb415b446 $5.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/11/06 99f35cfe037ce7200aab33a50ae0151c73244548
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/11/06 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.71
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-71.71
+
+2003/11/07 * (2134) 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ d27230e86aebbd6883e399ba2e38f635de9738a2 $21.09
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/11/07 * (2135) a453f317c358a729d5a4e85bcca7e21c3054d184
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $65.41
+ e5dfa7a292da1dd185fc7c6dd2402ec582a15f37 $51.32
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-116.73
+
+2003/11/07 * ce6771d870502fe52ab8ae77d8c7cab02879fde6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $30.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/08 bce1b4b2f7f58595ffbcefe4614aafe1269c3000
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/11/09 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/11 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.89
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/12 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.19
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-53.19
+
+2003/11/13 * 7994a463ade0f972bf1bb59ac236e37b08bfc4d7
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $11.14
+ e8a7204939bd995e0343c42de4366ad4fb95fe4d
+
+2003/11/13 * (2136) 4a8d2c1469dba4cbe5e7cd2a99bc287765ea105a
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $500.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/11/13 99f35cfe037ce7200aab33a50ae0151c73244548
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/11/13 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.83
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/14 * fd2d6dc6bf7e4124d5ddfa6a44275aa6d2f15ce8
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.14
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/15 a52b087bf5b2c8dba6d050f3cb79d42ce89826ff
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $16.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/11/16 * d66f20839763a4d86071659cdcbebaa6020203c3
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $21.97
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/11/16 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.24
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/16 * b3dee3f782518ed1c60469f04f4fdca82e619534
+ f2580c2fa4873496427487e068658993bbf70894 $16.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/11/17 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $6,061.95
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/11/17 * a91ab933c971ab9782b57b39377fc6b9aa878294
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $39.30
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/17 * 953388f315fdab9d0166aaa871ca84fc212af6fd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.52
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/17 * eb318e3f91d44bd7994f1be909b79e937415eced
+ f2580c2fa4873496427487e068658993bbf70894 $7.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/17 * 4886766974cb547d81289d92e2f87646a5715dcb
+ 59284ef86feceb946c427aeb6c0badfeb415b446 $19.90
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/18 99f35cfe037ce7200aab33a50ae0151c73244548
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/11/18 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $60.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-61.50
+
+2003/11/19 5d143d62e98809ac444b228114a6cfde901bad91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.08
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/11/19 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/19 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.99
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/11/20 * 97c39ef131bd74fb79b747076e3d51dfcd06a290
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $177.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/20 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.35
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/22 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $21.22
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/22 * 771469322c94ab3cb0b03e21018f3aa2b81abb11
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.29
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/22 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $24.54
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/23 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.52
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/11/23 * 95298d92d7000f1debf0ad06e7bd74c2af3823f4
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $10.31
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/23 * 478b8cf87b83049bacb3b8d81693a1a9ee1a2af9
+ f2580c2fa4873496427487e068658993bbf70894 $12.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/26 * dd68a4b38b001011fb067db32f136eb0a4790f95
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $146.30
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/28 * (2137) 923512d3f40f60de95daca10ec86a9810b1450ad
+ 3e2706db92ca6bb952333fd028e582695910c01d $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/11/29 * 1ea8657593769ea85cca3652ce0132a1905e6ddb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.34
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $47.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-68.34
+
+2003/11/29 * 987f1f9e420a473ad352b7ed9edf01e112842177
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.48
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/29 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.15
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/11/30 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $100.78
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2003/11/30 1e6df810ce83206bb4c563047d86d2a0b9765e65
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/11/30 c6f1f561f070c16cc7a1d989b24fd466e041f909
+ f2580c2fa4873496427487e068658993bbf70894 $7.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/11/30 * (2138) 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/12/01 * 846d6ebec66b4665b1e5ad1bad06a24dec170ab6
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $21.83
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/01 * 6e8301179a372b2284a1be31f62d401c2781b431
+ 5ea6ff037c50e85215211c1c1a25eebf6014611e $59.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/02 99f35cfe037ce7200aab33a50ae0151c73244548
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/12/02 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.29
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/02 * eb318e3f91d44bd7994f1be909b79e937415eced
+ f2580c2fa4873496427487e068658993bbf70894 $7.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/02 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/03 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.73
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/03 99f35cfe037ce7200aab33a50ae0151c73244548
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2003/12/03 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/03 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $25.54
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/04 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/05 * f16cc2af0679eeb768ff057766a607279f6dea24
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $8.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/06 * bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $23.93
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/07 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.28
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/08 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.84
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/08 * be95ab7efd9f203a652c73b9031c74106f994112
+ 181884ada86d2c3e7511e3ef3830fcf9f75b1421 $8.26
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/08 * bfc69ecff2f2a51ff65958bf2107a1d38daff373
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $29.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/08 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.08
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-57.08
+
+2003/12/09 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.01
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/10 * 5d143d62e98809ac444b228114a6cfde901bad91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.69
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $0.39
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-5.08
+
+2003/12/10 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.67
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/11 * f16cc2af0679eeb768ff057766a607279f6dea24
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $7.56
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/12 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.35
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/12 * eb318e3f91d44bd7994f1be909b79e937415eced
+ f2580c2fa4873496427487e068658993bbf70894 $4.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/13 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $25.43
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/14 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.28
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/14 * eb318e3f91d44bd7994f1be909b79e937415eced
+ f2580c2fa4873496427487e068658993bbf70894 $4.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/17 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.45
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-67.45
+
+2003/12/17 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/18 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $1,318.06
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/12/18 * 3ce79f1391f8596d7bead1a8ac4ef7f2b6948448
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $4.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/19 * eb318e3f91d44bd7994f1be909b79e937415eced
+ f2580c2fa4873496427487e068658993bbf70894 $4.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/19 * aba52d868db8a8abdbf5b6870eb786e08cbfae0c
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $22.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/19 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/20 * 22250d4f37cd5ca114deacbcce49798e78657179
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.89
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/20 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $22.59
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/20 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $22.82
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/21 * 6e011e2dd9b3f7b54c048e6b873c6242d6aaad3d
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.15
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/22 * (2139) 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ d27230e86aebbd6883e399ba2e38f635de9738a2 $33.53
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/12/22 * (2140) 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2003/12/22 * 6e1dffe991650653e71c21ac5c534f5bbb159f18
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.32
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/22 * da1821d1c660f3714496c84298561544a9d98bba
+ f2580c2fa4873496427487e068658993bbf70894 $16.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/23 * c6310ab22ed48f359022718d1b76e7876e9bb78b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $27.22
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/23 * 353483ad2a505c5f08dc1dc306993f394602c536
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $15.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/24 * 28ddee7891023e98fd5042ad8c0ed020d8658814
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $25.07
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/25 * 41f819b5353175ee634c3fc4ea22fcedee66762c
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.12
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $0.75
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-6.87
+
+2003/12/25 * 59e8bd32b95ddfd857b28cda46cd73ec96d1876e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $24.72
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/25 * 3837f7cdd2718dc7c9adb5697841d95b3b48e412
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/25 * 06f745c5b09afa8c983759d4f364191d7296a779
+ f2580c2fa4873496427487e068658993bbf70894 $8.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/26 * 42312536c687162574c9e3fc559f66328b16dc0a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.10
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/26 * 95b6b46bf9f262cf7aeffa04ba12d3bde9411eb6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $27.24
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/27 * b6d03fa2a031c97515cf8e68ab32b80b8df4b658
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $21.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-36.00
+
+2003/12/27 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.19
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/27 * b441f825276ddad8aac9f1d66da347350b2df1d0
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.03
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/28 * 624de2e9a0226301c5a73ed4a6cb48dc23ca03a7
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/29 * 04ff4313e11dca88fb1707316329ff143f8f78c2
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.02
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/29 * 299eb28835cafffe80dbb8398c478bd6b35b34bf
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/29 * c50ffe9fd9ab159d36900b2a90d0db4ddf70311e
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $15.06
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/29 * 7994a463ade0f972bf1bb59ac236e37b08bfc4d7
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $42.17
+ e8a7204939bd995e0343c42de4366ad4fb95fe4d
+
+2003/12/30 * 753f969617e5ddb15fff170a850849553001fa92
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.52
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/31 * fa39c23bd7d06b52f53d88060f6522ed961cc7e8
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $21.61
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/31 * 22b512a738ea5443add7cda4d716a447fc5e0a91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.97
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2003/12/31 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $103.70
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2004/01/03 * af636338204eb20a819cb1da004e0332d82b995e
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $8.61
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/03 * c87c800004660d7f8be464b70bddd89e660faf91
+ e940525b878f1783a30bf0cd9c040f6d27e0568c $9.15
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/04 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $2.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-102.00
+
+2004/01/04 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $22.94
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/05 * a8bca5fc944b8418636d585d965f0a4a5d172b2d
+ 5ea6ff037c50e85215211c1c1a25eebf6014611e $22.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/05 * 0d3afc5ee7dca0e4384f36c77ddee97a299f4799
+ 5ea6ff037c50e85215211c1c1a25eebf6014611e $12.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/05 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.15
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/06 * 04ff4313e11dca88fb1707316329ff143f8f78c2
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.02
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/06 * 38b7f9196b261fb4c1d940aedf1f9c1428392e54
+ 289db8ff9e0e3209f73fdeecb035f47c88396ff4 $508.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/06 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $34.37
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/07 * 753f969617e5ddb15fff170a850849553001fa92
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $35.88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/07 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $20.54
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/07 * f8d333e34c16de2be20b5dc8fe8e37c8cf0add70
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $18.41
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/08 * 6e011e2dd9b3f7b54c048e6b873c6242d6aaad3d
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.69
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/08 * bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $28.11
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/10 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.43
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/11 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.22
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/11 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.01
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/11 * eb318e3f91d44bd7994f1be909b79e937415eced
+ f2580c2fa4873496427487e068658993bbf70894 $81.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/12 * cbb4cc49824bf79827cde838e005848027ca0a38
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $5,000.00
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78
+
+2004/01/12 * 64b9f0a834be7951665cf032245a6a7c8c048d85
+ f2580c2fa4873496427487e068658993bbf70894 $13.99
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/01/14 * 5d143d62e98809ac444b228114a6cfde901bad91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.46
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/14 * 7695b47e54ee15e8a98913dc24a4c72ef8dc8be1
+ 9e67321982e83628563e8a2b396325aa18283ba5 $182.19
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/14 * 6a186a6a77b18206d98f2f4f875090a7c96ed118
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $19.47
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/15 * 4f70f05616f803772e7632a21030fdb33506c5f6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.71
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/16 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $979.13
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/01/16 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.93
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/16 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/17 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.14
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/17 * 50ddf3adbb7dba10abde203694dfe0b77cad138a
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $8.59
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/18 * 5cc3303576abdd30cc701f23fab05d15443ff6c1
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $25.69
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/17 * bc9899328c1c50c76dfa5068f02178b479ead0d2
+ 168eba32f6a6113fe447cd8516aa4d3544170084 $117.67
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/19 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $2.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-102.00
+
+2004/01/19 * 4d565ed871c3d07f2878d73e18576ceb83f8700b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.61
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/20 * d684e253a5be6ce373861f2ef69a37a10b0caaec
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $114.75
+ 1237fd153ab3077a51de74b5e659441b7bf6ef01 $13.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-128.25
+
+2004/01/20 * (2142) 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ d27230e86aebbd6883e399ba2e38f635de9738a2 $28.04
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/01/20 * (2143) a453f317c358a729d5a4e85bcca7e21c3054d184
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $16.86
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $16.84
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $0.70
+ e5dfa7a292da1dd185fc7c6dd2402ec582a15f37 $29.95
+ e5dfa7a292da1dd185fc7c6dd2402ec582a15f37 $29.95
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-94.30
+
+2004/01/20 * (2144) dd68a4b38b001011fb067db32f136eb0a4790f95
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $154.22
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/01/20 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/22 * (2145) b417958a5c0b64878801a502f469cf3687c02bb9
+ 59284ef86feceb946c427aeb6c0badfeb415b446 $90.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/01/23 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.77
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/26 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.28
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/27 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.22
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/27 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $23.78
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/29 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.12
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/30 * d684e253a5be6ce373861f2ef69a37a10b0caaec
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $33.85
+ 1237fd153ab3077a51de74b5e659441b7bf6ef01 $5.40
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-39.25
+
+2004/01/30 * 2ad323f9a17e92818c9ca3626175803d8e6eb1df
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $31.34
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/30 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.94
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/30 * 4f70f05616f803772e7632a21030fdb33506c5f6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/01/31 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $98.02
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2004/01/31 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/01 * (2146) 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/02/02 * d94a59cd70d2ae2ec1601cdfae3035a038f44bdc
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.35
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/03 * (2147) 8c08837348c1f28a7cc8547c98418ddf1344a6b3
+ 602986d0a44a1e0a1ab7f11691c70a1219131721 $24.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/02/03 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.35
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/03 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.85
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-58.85
+
+2004/02/04 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/05 * 0760a28df0204fe7687476a3d0692abea12019d0
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $250.00
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb
+
+2004/02/05 * 9041a4117789337045dfc4e608b5442192753977
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $50.00
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb
+
+2004/02/05 * (2148) a453f317c358a729d5a4e85bcca7e21c3054d184
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $46.81
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/02/05 * (2149) dd68a4b38b001011fb067db32f136eb0a4790f95
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $45.75
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/02/05 * (2150) 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $23.67
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/02/05 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.60
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/07 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $6.93
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/08 * e2045ef4a45bbf00e03b4b0f12d96980790ff80b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.87
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/08 * fe598f4e16bedbd2e3f7a2e0f78d7dc245671b81
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $11.98
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.21
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-20.19
+
+2004/02/12 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $2.97
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/12 * 316d046d288bef78213732e7e794f35dbe729ae3
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $109.97
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/14 * 713e03f61b59ddb873417498b33c61be1b3f44f5
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.60
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/14 * 7bd0f94e64d8a7deb15f2742228c01641e9b9a84
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $94.71
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/15 * 9af14dbc27d9b233cc6a2153d1235179faed6d9d
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $22.12
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/16 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $1,489.05
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/02/16 * 39ccba9779f59020ae45a9df08864376a1011b80
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.94
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/17 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $39.07
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/17 * 1cba536dbd4df3904a3d93f41c3967d07c56dcaa
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.75
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/18 * 9eda6f7f52f1168acdc85451c3f293fb932f8a7a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $45.27
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $30.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-75.27
+
+2004/02/19 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-101.50
+
+2004/02/19 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.58
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/20 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.12
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/20 * 953388f315fdab9d0166aaa871ca84fc212af6fd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/21 * e35225a98709b6e8dd0f331b96cc0d0a794b9cad
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $17.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/21 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $31.37
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/22 * ce6771d870502fe52ab8ae77d8c7cab02879fde6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $101.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-121.00
+
+2004/02/23 * 6e011e2dd9b3f7b54c048e6b873c6242d6aaad3d
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/23 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $31.58
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/26 * 46a7a458be73830dbf0160c876fb19f963bc733c
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.76
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/26 * c24a372e6acb6fb088a73bb23c4c625522c56dd4
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/29 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $82.91
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2004/02/29 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $29.40
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/02/29 * 95b6b46bf9f262cf7aeffa04ba12d3bde9411eb6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/03/01 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $26.52
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/03/01 * (2151) 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/01 * (2152) b417958a5c0b64878801a502f469cf3687c02bb9
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $250.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/01 * 7994a463ade0f972bf1bb59ac236e37b08bfc4d7
+ 628072f9bfc87daeb5e0144ef2090ef8057935e8 $181.74
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/02 * cbb4cc49824bf79827cde838e005848027ca0a38
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $5,000.00
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78
+
+2004/03/02 * 1b0cfd69357b7c20fb55adfc8fe5afa6ddffe80a
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $41.94
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/02 * 49bf3e3ca59241e4066bb3a50ea8d6564f303217
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/03 * 9ac21a761bd6c9a47860f1dfc51a37dea68b051d
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.68
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/04 * c50ffe9fd9ab159d36900b2a90d0db4ddf70311e
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $16.68
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/05 * b5a53b07e5ff84d945366dde1a100710e7bc2c2c
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.48
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/07 * 95b6b46bf9f262cf7aeffa04ba12d3bde9411eb6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $42.02
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/08 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $26.58
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/08 * 00fd0c8b4c6e05aee1fb76b2b961265f0dea3168
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.88
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/08 * af636338204eb20a819cb1da004e0332d82b995e
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $9.68
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/09 * 39ccba9779f59020ae45a9df08864376a1011b80
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.95
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/09 * b6d03fa2a031c97515cf8e68ab32b80b8df4b658
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.03
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/09 * 478b8cf87b83049bacb3b8d81693a1a9ee1a2af9
+ f2580c2fa4873496427487e068658993bbf70894 $4.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/09 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.19
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-52.19
+
+2004/03/10 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $25.86
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $29.90
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-55.76
+
+2004/03/10 * 40394c9f4ae1653ba4c7ef61eb70265bb119f227
+ f2580c2fa4873496427487e068658993bbf70894 $17.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/11 * e7e72b84f250cb56f3c7128b1c09a947b1aa03b7
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $12.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/03/11 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/13 * f3b7a362fa81544cf535165b88396e0a4a241c73
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $72.33
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/13 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $23.47
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/14 * ac52be5218b8d0b39697630e541f12d42c6ee135
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $49.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/14 * 2b474fcd668caa0d26b44adc77d410ac5e257bfd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.23
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/15 * 624de2e9a0226301c5a73ed4a6cb48dc23ca03a7
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $22.33
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/16 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $728.85
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/16 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $13.72
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/16 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/03/17 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/18 * 299eb28835cafffe80dbb8398c478bd6b35b34bf
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.06
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/18 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $26.09
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/18 * 729f7e00eb1e3dae7fd7fc9cc1af67af493444f7
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.99
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/21 * 8f2a9369c196f88970181565a81aab1d8816b126
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.13
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/21 * 478b8cf87b83049bacb3b8d81693a1a9ee1a2af9
+ f2580c2fa4873496427487e068658993bbf70894 $4.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/22 * 2ad323f9a17e92818c9ca3626175803d8e6eb1df
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $9.67
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/22 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $8.44
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/24 * 729f7e00eb1e3dae7fd7fc9cc1af67af493444f7
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.92
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/25 * 2971f8982324038e1c21d1928aa537c3e9d461af
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $30.77
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/25 * 2ad323f9a17e92818c9ca3626175803d8e6eb1df
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $7.10
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/26 * 40394c9f4ae1653ba4c7ef61eb70265bb119f227
+ f2580c2fa4873496427487e068658993bbf70894 $15.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/27 * 45d86d00b9617c9c8e82caa507fb718473c44e09
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $65.67
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $35.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-100.67
+
+2004/03/27 * 16eefd46b8e0282071752465137863f6347f7d44
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.68
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/27 * d245e9f1800efaf04f61c3a9a4385d5ed151ea6a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.56
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/28 * 216285097606392fb75c043c9155558b6ddbcaf5
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $5.37
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/28 * d7c9211568d4e88fab0fadadc5cef842e8fc7021
+ 168eba32f6a6113fe447cd8516aa4d3544170084 $60.25
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/28 * efc0cd23af4297386affbde9273a67913b0e9c49
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/29 * 2ad323f9a17e92818c9ca3626175803d8e6eb1df
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.62
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/30 * b23e1b7382f471ee532d7389a885b3982712f53e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $36.27
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/31 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $77.09
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2004/03/31 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.94
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-53.94
+
+2004/03/31 * b1192f2834401dc16af8b64643ae985c02cb4961
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.87
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/31 * c3fc7cbedf732de88ceab7f7fa34a592021d7024
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.13
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/03/31 * c3fc7cbedf732de88ceab7f7fa34a592021d7024
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.57
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/01 * 3c282ee44658366f1ad6b49c76f74038beedaa90
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $23.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/01 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $32.39
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/02 * be95ab7efd9f203a652c73b9031c74106f994112
+ 181884ada86d2c3e7511e3ef3830fcf9f75b1421 $7.40
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/02 * d66f20839763a4d86071659cdcbebaa6020203c3
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.17
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/02 * (2153) 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/02 * (2154) 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ d27230e86aebbd6883e399ba2e38f635de9738a2 $15.13
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/02 * (2155) a453f317c358a729d5a4e85bcca7e21c3054d184
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $114.76
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/02 * (2156) dd68a4b38b001011fb067db32f136eb0a4790f95
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $87.94
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/02 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $31.98
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.42
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-93.40
+
+2004/04/02 5478fc25bca0ae185f2c2d36781fc1840ac0b42a
+ f2580c2fa4873496427487e068658993bbf70894 $9.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/04/03 * 22ab203c3ad837c0bb91907851ec7c9260999120
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $526.94
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/03 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $25.05
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/04 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/05 * fafc3ee2608e739320f4cbe2db38fb45c30f64d0
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $54.40
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/05 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/06 2cbbc7f08aada2c9338bb1bc0e6dc05ed5fe76e1
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/04/06 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.24
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/07 * c4a01aa5c095dd8265c08b813276d84ac0788901
+ a7cefcc26daa42c746631597e921d13810dd1e5d $64.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/07 * 0760a28df0204fe7687476a3d0692abea12019d0
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $250.00
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb
+
+2004/04/07 * bea8d5e2678e516790a1d65f5c22875c1ee81f09
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $100.00
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb
+
+2004/04/07 * 335a0f6841267b99a0a147100392fed47b80e597
+ 9e67321982e83628563e8a2b396325aa18283ba5 $313.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/08 * c744bd69d5739cfe69ec89b0d0435a3ef4cdb1b0
+ 9e67321982e83628563e8a2b396325aa18283ba5 $99.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/08 * d684e253a5be6ce373861f2ef69a37a10b0caaec
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $150.45
+ 1237fd153ab3077a51de74b5e659441b7bf6ef01 $17.10
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-167.55
+
+2004/04/08 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $2.97
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/08 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $60.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-61.50
+
+2004/04/08 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.75
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/10 5478fc25bca0ae185f2c2d36781fc1840ac0b42a
+ f2580c2fa4873496427487e068658993bbf70894 $9.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/04/10 * 0bdfa162041573731f35ed9a115cebcceba07a68
+ 592a60e960113a755f70f9b58ef7a97b5aca14dc $69.90
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/10 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $1.98
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/10 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $15.84
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/11 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/11 * (2157) b8b586cfa1b2274a0bf946e5b9e53e92c185067c
+ e940525b878f1783a30bf0cd9c040f6d27e0568c $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/13 * e800eec67b4c03b445b61819cf8e1f7b27916f45
+ b70cb9532a007c1320479c559989bd9b7fc579c1 $272.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/13 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $25.41
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/14 * 0ca848f92d157881e94b313d91f9ecf364b3713a
+ a7cefcc26daa42c746631597e921d13810dd1e5d $19.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/15 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/15 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $655.43
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/15 * ce6771d870502fe52ab8ae77d8c7cab02879fde6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $29.64
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/16 * 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ d27230e86aebbd6883e399ba2e38f635de9738a2 $4.90
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/16 * a453f317c358a729d5a4e85bcca7e21c3054d184
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $85.33
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/16 * bb8b805afd42daedeadec2cd90fbfc10211ea0ea
+ 5ea6ff037c50e85215211c1c1a25eebf6014611e $146.16
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/16 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.84
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/18 * d66f20839763a4d86071659cdcbebaa6020203c3
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $30.11
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/18 * (2158) 50ddf3adbb7dba10abde203694dfe0b77cad138a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/18 * f159c0ab1d78ac3ddcd8264eed66b66516c7dd09
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.36
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/19 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $1.79
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/19 * 785d798d8a4706d97cb3bbea3041d23aa12bedad
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $16.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/20 * 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/20 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.72
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-67.72
+
+2004/04/20 * 3c0a1c540b2499a98fc4f07ff7e8bc35a0c4921e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $22.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/20 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/21 * 4f36cda4f67b75a4ef1e867a0a51313233c04879
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $8,103.00
+ 3d81529f3a4a694e57bbd6e63ffed2215bdef336
+
+2004/04/21 * 2a9649e01b659d9afcee414f35ac009fb43eed0c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $188.00
+ 3d81529f3a4a694e57bbd6e63ffed2215bdef336
+
+2004/04/21 * 504bbaf175bfba4956ef5dc3a38e1ff693874597
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $6,208.32
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4
+
+2004/04/21 * 1a1a6305d06ce4b284dba0d267c23f69d70c20be
+ fc0e191163be4d1966e3c51b1635401f9e82a807 70 AAPL
+ fc6f6f10f627ad1a5af9d488c98405a1498d019d $-5,000.00
+
+2004/04/21 * b45923836563f437a6394be8f4fd035bf7145f8d
+ fc0e191163be4d1966e3c51b1635401f9e82a807 -70 AAPL
+ f0d45665b22d0562833aa3bf373c5b15640d833e $-955.98
+ 49c6eb709b3d1613e4d6a1c04ee0ed9d23d665a4 $955.98
+ fc0e191163be4d1966e3c51b1635401f9e82a807 $1,911.96
+
+2004/04/21 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.32
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/22 * f1a1dcb303695a9107bef9686ec91b4fb3f2e19f
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $12.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/22 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.24
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/23 * (2159) 03642d4c8cfd39cbe8e1bbce3179a0ca53935e30
+ f0d45665b22d0562833aa3bf373c5b15640d833e $955.98
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/23 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $34.39
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/24 * 2204654c274e49b1a46ec1acbed7519645daddc6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $33.89
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/25 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.79
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-53.79
+
+2004/04/25 * a2fbb8ea26447c5ebd4f3de68a596027cc489649
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $43.70
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/26 * 20afab0a20b954305e459443a939ad2e51bc30ab
+ 59284ef86feceb946c427aeb6c0badfeb415b446 $26.41
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/25 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.01
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/26 * cbb4cc49824bf79827cde838e005848027ca0a38
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $1,913.00
+ fc0e191163be4d1966e3c51b1635401f9e82a807
+
+2004/04/26 5478fc25bca0ae185f2c2d36781fc1840ac0b42a
+ f2580c2fa4873496427487e068658993bbf70894 $9.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/04/26 * 612979bcaf308370105ac99e7dbbb8098f5b5b27
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.02
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/27 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/27 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/28 * dd68a4b38b001011fb067db32f136eb0a4790f95
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $44.18
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/28 * 91c59df073c8abd416047acbac4f38dd4834d955
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.16
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/04/28 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.04
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/29 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/30 * 6a186a6a77b18206d98f2f4f875090a7c96ed118
+ 9e67321982e83628563e8a2b396325aa18283ba5 $356.83
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $956.20
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-1,313.03
+
+2004/04/30 * f7dfe4fbd5e0b9027298ac1a5543cc0f5c2a2a30
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $86.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/30 * f7dfe4fbd5e0b9027298ac1a5543cc0f5c2a2a30
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $44.76
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/04/30 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $74.83
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2004/05/01 * 504bbaf175bfba4956ef5dc3a38e1ff693874597
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $2,916.66
+ 39189083b8637c7fff89e6bcf808790861417796
+
+2004/05/01 * (2160) 619cbfd21d72639f985324a9306696ce1262f3f6
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $13,000.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/01 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.89
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/03 * 07a24fc3a072f588a7498d8b94a37e0e587632dc
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.68
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/03 * bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $32.02
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/04 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.84
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-65.84
+
+2004/05/04 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/05 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $33.68
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/05 * 3c0a1c540b2499a98fc4f07ff7e8bc35a0c4921e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.05
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/06 * 02eeeedda75b06ccf47220e7020c8e1b705d67a4
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $10.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/07 * (2161) 8c08837348c1f28a7cc8547c98418ddf1344a6b3
+ 39ee34a6410884ea66b9f331c91f8383e2e592f0 $119.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/07 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/08 * (2162) 131a0c60d087a611e0a31601db68125e5a2dd4fc
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $22.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/09 * 275cc7006db94d75505db825dc5542aed9bfc26c
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $1,236.19
+ 0ecbb1b15e2cf3e515cc0f8533e5bb0fb2326728
+
+2004/05/09 * 9edce3fdc14e578091c4e785950f76c1691ac7a6
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $39.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/09 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $25.61
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-45.61
+
+2004/05/10 * bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $34.14
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/10 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $22.32
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/10 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $3.18
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/10 * cbb4cc49824bf79827cde838e005848027ca0a38
+ c56a21d23a6535184e7152ee138c28974f14280c 2,242.324241 BBBBB @ $22.7300000000000000000173472348
+ c56a21d23a6535184e7152ee138c28974f14280c 2,558.818182 DDDDD @ $8.9099999999999999998612221219
+ c56a21d23a6535184e7152ee138c28974f14280c 604.908255 FFFFF @ $41.3099999999999999999479582957
+ c56a21d23a6535184e7152ee138c28974f14280c -2,084.582278 AAAAA @ $24.4499999999999999972244424384
+ c56a21d23a6535184e7152ee138c28974f14280c -387.278233 LMVTX @ $58.8699999999999999998959165914
+ c56a21d23a6535184e7152ee138c28974f14280c -936.961582 GGGGG @ $26.6700000000000000000693889390
+ c56a21d23a6535184e7152ee138c28974f14280c $0.01
+
+2004/05/11 * 106e6bd420d331275023c76038ebb520502b39ef
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/12 * 729f7e00eb1e3dae7fd7fc9cc1af67af493444f7
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $26.48
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/12 * eb876715e4e911d1b72da43fa6e021225ac74ce0
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/13 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/13 * 26594b5abbc4e9dd869f14f1df59d43ebb4b91b6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $23.17
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/13 * bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $30.35
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/14 * f0c8ce7bc712cf25564004a6ab5a08be96d94504
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $53.40
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/14 * 40394c9f4ae1653ba4c7ef61eb70265bb119f227
+ f2580c2fa4873496427487e068658993bbf70894 $17.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/15 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $1,732.25
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/15 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.05
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/16 * 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ d27230e86aebbd6883e399ba2e38f635de9738a2 $17.21
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/16 * a453f317c358a729d5a4e85bcca7e21c3054d184
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $84.51
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/16 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $7.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/16 * 95b6b46bf9f262cf7aeffa04ba12d3bde9411eb6
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $41.48
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/17 * 1e6df810ce83206bb4c563047d86d2a0b9765e65
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.48
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/17 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $28.77
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/17 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $9.98
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/17 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $40.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-41.50
+
+2004/05/18 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.69
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/18 * 9401381d21c8b210d51407a7281b2979c6934bbf
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.41
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/18 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.03
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/18 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $10.51
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/18 * 0fb419d273cdd0cfe9825e94f91c2058e99c1f7a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.68
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/18 * c50ffe9fd9ab159d36900b2a90d0db4ddf70311e
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $3.77
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/19 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $23.13
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/19 * (2163) db96a59e17a29aba685420d1f72271cb0e2d4be2
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $37.12
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/19 * 0fb419d273cdd0cfe9825e94f91c2058e99c1f7a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.10
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/19 * 478b8cf87b83049bacb3b8d81693a1a9ee1a2af9
+ f2580c2fa4873496427487e068658993bbf70894 $4.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/20 * 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/20 * b6d03fa2a031c97515cf8e68ab32b80b8df4b658
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.19
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/20 * f7dfe4fbd5e0b9027298ac1a5543cc0f5c2a2a30
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $11.27
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/21 * b1b1ed463af52a975722e23887c94b652b4ad7e2
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $15.32
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/21 * 61ec80beb9a6f44903c8f6559f7051962cbac447
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.38
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/21 * 8f2a9369c196f88970181565a81aab1d8816b126
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.02
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/21 * 97a7a570c8ede9be3bb8ca6edb1ee14e1012c595
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.65
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/21 * f7dfe4fbd5e0b9027298ac1a5543cc0f5c2a2a30
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $3.52
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/21 * 015c9e35cf2dcd43a6dc42ab8ee65dc48bf89b91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.14
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/22 * 49bf3e3ca59241e4066bb3a50ea8d6564f303217
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $23.22
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/22 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $23.01
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/22 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.50
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-101.50
+
+2004/05/23 * 2172039ae1b9ef750b090fbe98e8b3fdc1a3553e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $26.86
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/23 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.80
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/23 * 771469322c94ab3cb0b03e21018f3aa2b81abb11
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.58
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/25 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $34.39
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/25 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.38
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/25 * 61ad50a9b9189cc3cf1874568e35e7901ff4c982
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.01
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/26 * d66f20839763a4d86071659cdcbebaa6020203c3
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $32.26
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/26 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.71
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/26 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.49
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/27 * 06e1515d7acf1e9b3869e82b570fd55c60ed97c2
+ 5ea6ff037c50e85215211c1c1a25eebf6014611e $13.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/27 * a46af6931d9dace2200617548fab3274549e308f
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $58.70
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/27 26bb0e8d147d95e73f96c919636363ebc9d53037
+ (8ccfbea4d5d39235320ffeffe845cb68ef297cb9) $256.90
+
+2004/05/28 * 1c1bb064786be7eb3461145f0c18b033b1ffe9ef
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $329.72
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/28 * 78565e2e4c37cefe941dd5fe4adec3e71f1b3456
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $95.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/28 * f159c0ab1d78ac3ddcd8264eed66b66516c7dd09
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.34
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/28 * 00d188d123568c8992f208c9566d50bdc9d426ee
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $0.41
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb $-0.30
+ ff7d6181c581373db166118e7fd34bfa6f3f2dcb $-0.11
+
+2004/05/29 * a2fbb8ea26447c5ebd4f3de68a596027cc489649
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $34.17
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/30 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/30 * 953388f315fdab9d0166aaa871ca84fc212af6fd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/05/30 * (2165) 131a0c60d087a611e0a31601db68125e5a2dd4fc
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/05/31 * 09462753ff102b976a33e75fdde093d4ad6e39ca
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.04
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-34.04
+
+2004/05/31 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $90.65
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2004/06/01 * d66f20839763a4d86071659cdcbebaa6020203c3
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $30.88
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/01 * dd68a4b38b001011fb067db32f136eb0a4790f95
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $44.18
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/01 * 9675f80d41147aee96475d47554f4b0de421ad4e
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $58.15
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/01 * 5204ec41dca3d276c560c5baa59f2e15aad5efc5
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $103.99
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/01 * d682d553b633ed402c13806e6d05f3282c30dc47
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $24.94
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/01 * a1bd7d7413519862e1950f81b1b947c19374cb4a
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $12.00
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $9.50
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $21.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-42.50
+
+2004/06/01 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/01 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/01 * 612979bcaf308370105ac99e7dbbb8098f5b5b27
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.12
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-35.12
+
+2004/06/01 * 94feb6c59fff720bb427d719c5086944b11ecfe5
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $1.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/02 * b39b0c179cab6038532c65b62310ee775d65dd94
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $99.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/02 * c4cd18eae2f9b743b28811ddc30c87ad961c46af
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $204.97
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/02 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $28.91
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/03 * a91ab933c971ab9782b57b39377fc6b9aa878294
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $21.11
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/03 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.01
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/04 * 1bbbcf3a6fcd46c18d81d70cab39387674500013
+ 39ee34a6410884ea66b9f331c91f8383e2e592f0 $108.24
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/04 * 504bbaf175bfba4956ef5dc3a38e1ff693874597
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $2,916.66
+ 39189083b8637c7fff89e6bcf808790861417796
+
+2004/06/04 * 504bbaf175bfba4956ef5dc3a38e1ff693874597
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $138.50
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4
+
+2004/06/04 * (2166) cb366c5b066ce919fb87eabefef0556bbfaf81c0
+ 2ff50cab09d039eaa717cac29cf2759eb39a007d $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/05 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/05 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.71
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/06 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.28
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/07 * c4cd18eae2f9b743b28811ddc30c87ad961c46af
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $9.04
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/07 * c4cd18eae2f9b743b28811ddc30c87ad961c46af
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $20.99
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/07 * (2167) 74c62adeb5902bbcee5761fd626e81958b18170d
+ 602986d0a44a1e0a1ab7f11691c70a1219131721 $152.25
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/10 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $25.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/10 * 6a186a6a77b18206d98f2f4f875090a7c96ed118
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $43.29
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/11 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/12 * 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $2.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-102.00
+
+2004/06/12 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $27.13
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/13 * 612979bcaf308370105ac99e7dbbb8098f5b5b27
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.91
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/13 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.67
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/14 * f1a1dcb303695a9107bef9686ec91b4fb3f2e19f
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $12.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/14 * bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $31.34
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/15 * 2c8ac236bcc8813497becd0e65a0aba085b05606
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $30.40
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/15 * 2c8ac236bcc8813497becd0e65a0aba085b05606
+ 326b155986fe005914c2cd52851da075ff65992f $18.13
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/15 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $2,342.71
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/15 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.83
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/16 * 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ d27230e86aebbd6883e399ba2e38f635de9738a2 $17.44
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/16 * a453f317c358a729d5a4e85bcca7e21c3054d184
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $83.44
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/18 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/19 * 1fc8bdc3f19a570ae59f18f676c770d9ef0ae27a
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $14.49
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/19 * 1fc8bdc3f19a570ae59f18f676c770d9ef0ae27a
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $11.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/19 * a46af6931d9dace2200617548fab3274549e308f
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $28.49
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/19 * a91ab933c971ab9782b57b39377fc6b9aa878294
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $10.83
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/19 * b422694a3e6330fa33f2996acb27cc83093c1cdf
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $9.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/19 * 61ad50a9b9189cc3cf1874568e35e7901ff4c982
+ dc11d67d6cc4ca6136c8690e387e70772dcb8465 $9.17
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/20 * 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/20 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $25.87
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/20 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.22
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/21 * (2168) b8b586cfa1b2274a0bf946e5b9e53e92c185067c
+ e940525b878f1783a30bf0cd9c040f6d27e0568c $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/06/21 * be95ab7efd9f203a652c73b9031c74106f994112
+ 181884ada86d2c3e7511e3ef3830fcf9f75b1421 $8.82
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/21 * a49dd639ccbaa09aa85d8426ade6e5ffad910f49
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $3.33
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/21 * a49dd639ccbaa09aa85d8426ade6e5ffad910f49
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $9.17
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/21 * 09462753ff102b976a33e75fdde093d4ad6e39ca
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.49
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/21 * a95c40f310c47178537882d69dcfe6b8b1dcc080
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $2.71
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/21 * 987f1f9e420a473ad352b7ed9edf01e112842177
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $6.48
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/21 * aa5653a7a2f2eee41b9af0acf35848fa1e00bf34
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $5.77
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/21 * bebe255c0d6885334049a7c26159237f1a815bbc
+ 2d059a4c9183c0ad073f02076c5184c8fa8eaed6 $77.93
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/21 * 6a186a6a77b18206d98f2f4f875090a7c96ed118
+ 8ccfbea4d5d39235320ffeffe845cb68ef297cb9 $32.46
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/22 * 3c0a1c540b2499a98fc4f07ff7e8bc35a0c4921e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $23.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/23 * 3d363ed8ccc251083432b152f1b4c9c2d82f8941
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.40
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/23 * 1cdc2c2d06318a1f26e380931650cc576f462076
+ ca268d538b1a0056c1e3c8c5874d4cb30452d738 $28.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/23 * a2fbb8ea26447c5ebd4f3de68a596027cc489649
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $59.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/24 * 5186baea3db85c63ab38c4698daa14a530670c4a
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.53
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/24 * bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $33.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/25 * 1cdc2c2d06318a1f26e380931650cc576f462076
+ ca268d538b1a0056c1e3c8c5874d4cb30452d738 $56.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/25 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $23.97
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/26 * 1cdc2c2d06318a1f26e380931650cc576f462076
+ ca268d538b1a0056c1e3c8c5874d4cb30452d738 $28.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/26 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/26 * 1cdc2c2d06318a1f26e380931650cc576f462076
+ ca268d538b1a0056c1e3c8c5874d4cb30452d738 $28.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/27 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $1.41
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/27 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.31
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/27 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $20.76
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/28 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $15.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/28 * ab4621385974a232c17c229d8b2b4eb75f13ba51
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $27.98
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/29 * 6e011e2dd9b3f7b54c048e6b873c6242d6aaad3d
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $16.46
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/29 * 7b3318b6fa2d182878fd4fa214b2b2d16d122d5e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $27.52
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/30 * d2667e42a8beac84d6f95887ab807a947a425d67
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $28.89
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/30 * bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $32.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/06/30 * 3a12015d49db73ea5d5dcdf3d749b49b3a0240ad
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78 $89.48
+ 5c40e29310f67c1d38cd0a6251819dc2860aab37
+
+2004/07/01 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $28.11
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-78.11
+
+2004/07/01 * 504bbaf175bfba4956ef5dc3a38e1ff693874597
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $2,916.66
+ 39189083b8637c7fff89e6bcf808790861417796
+
+2004/07/01 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/01 * 2c8ac236bcc8813497becd0e65a0aba085b05606
+ 326b155986fe005914c2cd52851da075ff65992f $34.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/01 * 2c8ac236bcc8813497becd0e65a0aba085b05606
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $57.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/01 * 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/02 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $23.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/03 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $16.12
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/03 * 612979bcaf308370105ac99e7dbbb8098f5b5b27
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $28.49
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/05 * 3c0a1c540b2499a98fc4f07ff7e8bc35a0c4921e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.05
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/05 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.16
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/06 * f7dfe4fbd5e0b9027298ac1a5543cc0f5c2a2a30
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $429.11
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/06 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.16
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/07 * 5d143d62e98809ac444b228114a6cfde901bad91
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.56
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/08 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $26.58
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-46.58
+
+2004/07/09 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $34.49
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/09 * 48e6fffc4cd537c2c9a9ac6b751dc8674bcd00ba
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $27.24
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/11 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.18
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/12 * (2169) 25dfaea64340892890c1ca4d522b08ade0aeb689
+ 2ff50cab09d039eaa717cac29cf2759eb39a007d $75.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/12 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.31
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/13 * 4d565ed871c3d07f2878d73e18576ceb83f8700b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $10.97
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/14 * be95ab7efd9f203a652c73b9031c74106f994112
+ 181884ada86d2c3e7511e3ef3830fcf9f75b1421 $4.90
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/14 * 27b88c0ce2f9724bd30a23beb098e01587e0c801
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.23
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/15 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $1,301.46
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/16 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.77
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/16 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.20
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/17 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.71
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-68.71
+
+2004/07/18 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.45
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/18 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $33.98
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/18 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/19 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.95
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/19 * 7695b47e54ee15e8a98913dc24a4c72ef8dc8be1
+ 3e2706db92ca6bb952333fd028e582695910c01d $173.20
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/19 * f1a1dcb303695a9107bef9686ec91b4fb3f2e19f
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $12.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/19 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.75
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/20 * 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/20 * 6ddb45499d05454b04e5102c359918a7ecc3eff7
+ 602986d0a44a1e0a1ab7f11691c70a1219131721 $215.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/20 * fafc3ee2608e739320f4cbe2db38fb45c30f64d0
+ 7134396063db3d3d81defdb1a2c68ee1383d199f $49.99
+ 6d93163434f5b2253b3b5283f6015b60c79ea659 $36.15
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-86.14
+
+2004/07/20 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.79
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/21 * a46af6931d9dace2200617548fab3274549e308f
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $22.32
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/21 * 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ d27230e86aebbd6883e399ba2e38f635de9738a2 $23.80
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/21 * dd68a4b38b001011fb067db32f136eb0a4790f95
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $44.18
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/21 * a453f317c358a729d5a4e85bcca7e21c3054d184
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $79.91
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/21 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/21 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.49
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/23 * bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $19.48
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/23 * bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $12.82
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/23 * 47fee5bd794ca475684e9504bb438cd678916394
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.71
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/23 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $25.47
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-125.47
+
+2004/07/23 * 74c0fda1054b04bf3e2365d467e32a47e3feba7b
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $6.77
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/23 * 74c0fda1054b04bf3e2365d467e32a47e3feba7b
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $10.43
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/23 * 74c0fda1054b04bf3e2365d467e32a47e3feba7b
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $5.86
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/23 * 74c0fda1054b04bf3e2365d467e32a47e3feba7b
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $3.98
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/25 * 9861ce541c17b11f627e71c26bf350b33141f62b
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $20.15
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/25 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/26 * 98c898a0676fe2b3cb0ffff81413d0989eb8a2b8
+ 602986d0a44a1e0a1ab7f11691c70a1219131721 $37.45
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/26 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.52
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/26 * a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/27 5478fc25bca0ae185f2c2d36781fc1840ac0b42a
+ f2580c2fa4873496427487e068658993bbf70894 $9.75
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/07/27 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.15
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/27 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.65
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/27 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.41
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/27 * 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.46
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/30 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $22.93
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/30 * 11d9eca019dbb06dc7cee01986ca2a4d43c30954
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.78
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/31 0b5722c2c27395bb81c2c6b548e3f5ae45180047
+ f2580c2fa4873496427487e068658993bbf70894 $10.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/07/30 * aadc967ebc7363b9ddadb35853de59ec10c09e72
+ e5dfa7a292da1dd185fc7c6dd2402ec582a15f37 $36.46
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/07/30 * e13b2a90bf864183a5ee1bf879ae41813eca623b
+ e5dfa7a292da1dd185fc7c6dd2402ec582a15f37 $7.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/07/31 9fca7b8d5eb6cc9b0272edc33d05a50c77fa5589
+ f2580c2fa4873496427487e068658993bbf70894 $8.75
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/07/31 * b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $33.65
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/01 * b16891cc36681d41e678846933c29807a202e7c4
+ e5dfa7a292da1dd185fc7c6dd2402ec582a15f37 $5.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/01 * 504bbaf175bfba4956ef5dc3a38e1ff693874597
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $3,369.77
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $-453.11
+ 39189083b8637c7fff89e6bcf808790861417796 $-2,916.66
+
+2004/08/01 * 2c8ac236bcc8813497becd0e65a0aba085b05606
+ 326b155986fe005914c2cd52851da075ff65992f $34.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/01 * 2c8ac236bcc8813497becd0e65a0aba085b05606
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $57.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/02 * 612979bcaf308370105ac99e7dbbb8098f5b5b27
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $16.48
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/02 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.79
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-54.79
+
+2004/08/03 * 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.11
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/03 * 2f7e9e35b7b925be61a94554e17b97e69de0e64b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.07
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/04 * 835783fc1d053900e29b92be85e47024796c3ee5
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.27
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/05 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.18
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/05 * 2ad323f9a17e92818c9ca3626175803d8e6eb1df
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.80
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/06 * 40394c9f4ae1653ba4c7ef61eb70265bb119f227
+ f2580c2fa4873496427487e068658993bbf70894 $17.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/06 * a54e655c93b4e8a987bd82d9a20d10e5078c091c
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.71
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/06 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/06 * 6311a5e415b6218c88c877cf57d459a79a646a22
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $9.64
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/06 * afa70d90f551d4ff605bb4f4e0312ccae0ccb510
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $23.91
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/07 * cdbd6445b409d06d3bbeee9ad27c1d535ba7f6df
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $24.36
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/07 * 4d565ed871c3d07f2878d73e18576ceb83f8700b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.18
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/08 * ac52be5218b8d0b39697630e541f12d42c6ee135
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.37
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/08 * 99da57dbbf75179d8ed5631fd0ccc588bd2c96d2
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $27.40
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/09 * eda59694400ba3aa79c7cb6ac131c643b119ad02
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $29.69
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/09 * 691ee60203f0e6df7344c4ffea35246d9fa22b96
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.11
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/10 * fc46581f9108f358044a454da70a26213d20abe0
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $70.04
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/10 * 691ee60203f0e6df7344c4ffea35246d9fa22b96
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.19
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/10 * 914ad295d9b70cdde0d6d7e20ea2da61c29327f1
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.75
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/11 * b0fd790e67ed296e4557dba02f51d2178ca15921
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.09
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/11 * 97a7a570c8ede9be3bb8ca6edb1ee14e1012c595
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.57
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/11 * cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.96
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/11 * 2ad323f9a17e92818c9ca3626175803d8e6eb1df
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.05
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/11 * 7592910fc29b651a46c7c700406ed51978ae4cd6
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $24.30
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/11 * 6427432c39e8152357f8e82fd8399d118e199aa9
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.09
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/12 * e913379262b39496a6c00427697284cd786eb20d
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.87
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/13 2bb2072d9321de0d9b8030664c8a9333fdfa4a85
+ f2580c2fa4873496427487e068658993bbf70894 $5.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/08/13 * b6d03fa2a031c97515cf8e68ab32b80b8df4b658
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/13 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.86
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/14 * 2470dca59588f4db61caa65758dc3be6e848d811
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/14 * 2ad323f9a17e92818c9ca3626175803d8e6eb1df
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.18
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-23.18
+
+2004/08/15 * 0d9318bfa76160b6540a892d20f413e9a989b8ca
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $1,626.35
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/08/16 a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.74
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/16 bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $13.08
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/16 f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.93
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/16 * 74c0fda1054b04bf3e2365d467e32a47e3feba7b
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $3.45
+ 92a772d9a491a8c8f239d9148b979f1da7369480
+
+2004/08/17 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $27.22
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/19 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $1.98
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/19 f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $22.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $20.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-42.50
+
+2004/08/19 6311a5e415b6218c88c877cf57d459a79a646a22
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $7.04
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/19 612979bcaf308370105ac99e7dbbb8098f5b5b27
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $16.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/19 953388f315fdab9d0166aaa871ca84fc212af6fd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.24
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/20 * f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $2.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $40.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-42.50
+
+2004/08/20 * 9b0b9af3274adf9514e492055259b4f9c17ce067
+ 463628a20f371d71d46a7947f1175a0c16ce2f45 $950.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/08/21 * 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ d27230e86aebbd6883e399ba2e38f635de9738a2 $29.17
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/08/21 * a453f317c358a729d5a4e85bcca7e21c3054d184
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $79.46
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/08/21 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $14.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/08/21 d06547b2db2bfaa2e5e16a117f51635c8d851667
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.25
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/22 * dd68a4b38b001011fb067db32f136eb0a4790f95
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $49.35
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/08/22 * 4ffc4349510313ea639fc1e50d7e156c456cdb84
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $67.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/08/24 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.95
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/24 685f23bc5eb93fc982292395e8c03a40670ce3ec
+ eb0c1e3629fe7cba500081ef756a72e9659a93c4 $113.60
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/25 dd68a4b38b001011fb067db32f136eb0a4790f95
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $49.41
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/08/25 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $100.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $2.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-102.00
+
+2004/08/25 cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.05
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/25 973b27747b462069cd89ef63ac7fea9f431caca9
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.46
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/25 b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $32.94
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/27 f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $25.77
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/27 a23f4dd42eb312db32096c3bb1766d31d4bb6c42
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $11.75
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/28 c0458f2551bfdbbaa65666d6cc9a4b918bc48520
+ f2580c2fa4873496427487e068658993bbf70894 $9.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/08/28 5a82e1f39afdb31637d2e54d696aac20e9449a6a
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $37.94
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/28 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.84
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/29 5478fc25bca0ae185f2c2d36781fc1840ac0b42a
+ f2580c2fa4873496427487e068658993bbf70894 $9.75
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/08/29 2470dca59588f4db61caa65758dc3be6e848d811
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.48
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/08/30 8c48fe5998e43553a8af87a1959965ff9e5f1c6e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $6.71
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/30 4d565ed871c3d07f2878d73e18576ceb83f8700b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $15.37
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/08/30 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.89
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/01 2c8ac236bcc8813497becd0e65a0aba085b05606
+ 326b155986fe005914c2cd52851da075ff65992f $34.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/01 2c8ac236bcc8813497becd0e65a0aba085b05606
+ ab0ddaf550edf34ce2f7937aa3fb073d0240e8af $57.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/01 bdc1fd5d3c0f3dcfd55d010426e61bf9451e680d
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $21.67
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/01 169151bd9488fb3e03ca31d580666e68aa2f20f0
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.48
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/01 c30acab5abcb7bb89524aa9f3daeeeb6de317c0e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.19
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/02 046bb9cbb1f66bbca5bafa458fbe943c998a5552
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $24.32
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/03 03927f700749296a9e4ae0e7794cd87bf645274b
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $60.00
+ cecae7f2312046d2775a401cc3c3925b79676ce3 $3.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-63.00
+
+2004/09/03 64c56683e1f14d64fe46bcf2763bcdc3db96e5a9
+ c233d176ce06c06ecfd032230c4be5ff4476a554 $17.15
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/09/03 10f29adc761ed3c5d5b4b7e4492919b75da151c8
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.51
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/09/04 cdc9806b703b6568d2e27bd0424c0e04938e2cff
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $16.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/04 50126a4484b34cea63f9724bea04d03cd3c2b611
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $8.35
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/09/05 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $23.43
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/06 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.88
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/07 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $9.36
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/07 f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $19.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/08 612979bcaf308370105ac99e7dbbb8098f5b5b27
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $16.50
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/08 5478fc25bca0ae185f2c2d36781fc1840ac0b42a
+ f2580c2fa4873496427487e068658993bbf70894 $9.75
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/09/09 b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $30.70
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/10 5478fc25bca0ae185f2c2d36781fc1840ac0b42a
+ f2580c2fa4873496427487e068658993bbf70894 $19.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/09/10 f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.59
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-53.59
+
+2004/09/12 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $7.85
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/12 eb318e3f91d44bd7994f1be909b79e937415eced
+ f2580c2fa4873496427487e068658993bbf70894 $8.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/09/12 f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.81
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/13 3089591a3cd997b0823611f3ffe89b0f525ee88e
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $4.35
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/09/14 619cbfd21d72639f985324a9306696ce1262f3f6
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $3,000.00
+ 7bd474a1c1d1afd2a0f22b563206deec4aba3e78
+
+2004/09/15 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $2.97
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/15 77b9c5798a3049c3628dd7222459de0d251a4e8b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $25.57
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/15 b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $23.47
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/15 4d565ed871c3d07f2878d73e18576ceb83f8700b
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $12.87
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/16 f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/17 f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $5.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/17 3c0a1c540b2499a98fc4f07ff7e8bc35a0c4921e
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $17.55
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/18 eb318e3f91d44bd7994f1be909b79e937415eced
+ f2580c2fa4873496427487e068658993bbf70894 $8.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/09/18 c6408f67e3464256a4b56579f30647ac52a79ce0
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $18.77
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/19 5478fc25bca0ae185f2c2d36781fc1840ac0b42a
+ f2580c2fa4873496427487e068658993bbf70894 $9.75
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $29.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/09/19 549c950857bf4f194f2d93cf98db69f9cdba2a8c
+ 52e5ccdac27116d2919ae560eb4021c5addf9ca8 $0.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/21 66ed7e5615e2e59ea9ea2aa99a12243dbe0559c7
+ d27230e86aebbd6883e399ba2e38f635de9738a2 $17.21
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/09/21 a453f317c358a729d5a4e85bcca7e21c3054d184
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $79.56
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
+2004/09/21 685f23bc5eb93fc982292395e8c03a40670ce3ec
+ 92a772d9a491a8c8f239d9148b979f1da7369480 $8.65
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/21 f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $28.34
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/22 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.91
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/23 0b209e14dc9dab896b962d3be3b5ab5808eac7cb
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $4.99
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/24 eb318e3f91d44bd7994f1be909b79e937415eced
+ f2580c2fa4873496427487e068658993bbf70894 $8.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/09/24 f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $21.65
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $50.00
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $-71.65
+
+2004/09/25 4df0c1da9898d6fc18ed9dbdd567ffbe3ec6f803
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $20.00
+ cfd76529eda7575c434ab6edd70e56693f979bb1 $15.00
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9 $-35.00
+
+2004/09/26 f753d77018be3e691ddf8c33796a33a7b36d39d8
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $23.87
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/26 b007369e15aba78cb6075310da96b854f5448a3a
+ 3282f21c97a0e1f66185923328d80d87fa5d8db7 $26.67
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/26 f60050f870fc94a605d842605a2f366384de9962
+ f2580c2fa4873496427487e068658993bbf70894 $9.50
+ cfd76529eda7575c434ab6edd70e56693f979bb1
+
+2004/09/26 80090f9d547f344402581e8a5dd6b5e71a342104
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.80
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/27 f6bc13e8a66d6bbdf8de6753aab036cc1c8db980
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $13.15
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/09/28 cb232a7a7077aa499f78ccdd5b4238a3ff1a4dcd
+ 1b565047893eb8f55e839a9f0b5259d047547a82 $3.05
+ f0eb264dac24ed3a12eded5dfc3e3498e4ab13b9
+
+2004/10/01 504bbaf175bfba4956ef5dc3a38e1ff693874597
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42 $2,916.66
+ 39189083b8637c7fff89e6bcf808790861417796
+
+2004/09/21 dd68a4b38b001011fb067db32f136eb0a4790f95
+ 9c484b5dc87055f93751ad00947fd9a7a14ea470 $44.28
+ fa9806a79e9cdf26d36d53646dd0aa2f70419c42
+
diff --git a/test/input/transfer.dat b/test/input/transfer.dat
new file mode 100644
index 00000000..1e2991dc
--- /dev/null
+++ b/test/input/transfer.dat
@@ -0,0 +1,220 @@
+2004/08/02 Transfer to hcoop.net
+ Expenses:Internet 59820 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/02 Transfer to hcoop.net
+ Expenses:Internet 58626 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/02 Transfer to hcoop.net
+ Expenses:Internet 2997279 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/03 Transfer to hcoop.net
+ Expenses:Internet 227266 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/03 Transfer to hcoop.net
+ Expenses:Internet 54375 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/05 Transfer to hcoop.net
+ Expenses:Internet 54353 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/07 Transfer to hcoop.net
+ Expenses:Internet 54353 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/16 Transfer to hcoop.net
+ Expenses:Internet 54353 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/20 Transfer to hcoop.net
+ Expenses:Internet 133967 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/20 Transfer to hcoop.net
+ Expenses:Internet 124438 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/21 Transfer to hcoop.net
+ Expenses:Internet 148691 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/22 Transfer to hcoop.net
+ Expenses:Internet 660168 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/22 Transfer to hcoop.net
+ Expenses:Internet 2876287 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/24 Transfer to hcoop.net
+ Expenses:Internet 55166 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/24 Transfer to hcoop.net
+ Expenses:Internet 54743 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/28 Transfer to hcoop.net
+ Expenses:Internet 2414720 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/30 Transfer to hcoop.net
+ Expenses:Internet 396873 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/30 Transfer to hcoop.net
+ Expenses:Internet 2482301 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/08/31 Transfer to hcoop.net
+ Expenses:Internet 3696731 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/01 Transfer to hcoop.net
+ Expenses:Internet 2748364 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/05 Transfer to hcoop.net
+ Expenses:Internet 2500517 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/06 Transfer to hcoop.net
+ Expenses:Internet 54910 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/06 Transfer to hcoop.net
+ Expenses:Internet 9196055 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/07 Transfer to hcoop.net
+ Expenses:Internet 2640950 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/07 Transfer to hcoop.net
+ Expenses:Internet 94442 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/08 Transfer to hcoop.net
+ Expenses:Internet 2579158 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/08 Transfer to hcoop.net
+ Expenses:Internet 530904 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/08 Transfer to hcoop.net
+ Expenses:Internet 27368 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/08 Transfer to hcoop.net
+ Expenses:Internet 6593 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/08 Transfer to hcoop.net
+ Expenses:Internet 279 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/08 Transfer to hcoop.net
+ Expenses:Internet 773 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/09 Transfer to hcoop.net
+ Expenses:Internet 4217461 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/10 Transfer to hcoop.net
+ Expenses:Internet 100241 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/10 Transfer to hcoop.net
+ Expenses:Internet 117866 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/10 Transfer to hcoop.net
+ Expenses:Internet 111275 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/11 Transfer to hcoop.net
+ Expenses:Internet 2717020 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/12 Transfer to hcoop.net
+ Expenses:Internet 88188 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/13 Transfer to hcoop.net
+ Expenses:Internet 3046553 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/13 Transfer to hcoop.net
+ Expenses:Internet 3370971 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/13 Transfer to hcoop.net
+ Expenses:Internet 2941407 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/13 Transfer to hcoop.net
+ Expenses:Internet 2101943 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/15 Transfer to hcoop.net
+ Expenses:Internet 3050131 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/15 Transfer to hcoop.net
+ Expenses:Internet 2638687 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/15 Transfer to hcoop.net
+ Expenses:Internet 2668178 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/16 Transfer to hcoop.net
+ Expenses:Internet 2645212 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/17 Transfer to hcoop.net
+ Expenses:Internet 336579 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/17 Transfer to hcoop.net
+ Expenses:Internet 104305 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/18 Transfer to hcoop.net
+ Expenses:Internet 3117533 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/19 Transfer to hcoop.net
+ Expenses:Internet 120777 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/20 Transfer to hcoop.net
+ Expenses:Internet 193151 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/20 Transfer to hcoop.net
+ Expenses:Internet 56204 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/21 Transfer to hcoop.net
+ Expenses:Internet 315126 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/22 Transfer to hcoop.net
+ Expenses:Internet 138076 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/09/24 Transfer to hcoop.net
+ Expenses:Internet 817190 bytes
+ Liabilities:Payable:hcoop.net
+
+2004/10/05 Transfer to hcoop.net
+ Expenses:Internet 356104 bytes
+ Liabilities:Payable:hcoop.net
+
diff --git a/test/input/wow.dat b/test/input/wow.dat
new file mode 100644
index 00000000..20b63ef7
--- /dev/null
+++ b/test/input/wow.dat
@@ -0,0 +1,550 @@
+C 1.00s = 100c
+C 1.00G = 100s
+
+D 1.00G
+
+2006/03/14 Opening Balances
+ Assets:Tajer 1339829c
+ Assets:Gruulmorg 248720c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1428c
+ Expenses:Fees:Auction 768c
+ Expenses:Fees:Auction 612c
+ Expenses:Fees:Auction 4764c
+ Expenses:Fees:Auction 3372c
+ Expenses:Fees:Auction 1296c
+ Expenses:Fees:Auction 1332c
+ Expenses:Fees:Auction 660c
+ Expenses:Fees:Auction 10044c
+ Expenses:Fees:Auction 3588c
+ Expenses:Fees:Auction 1632c
+ Expenses:Fees:Auction 8388c
+ Expenses:Fees:Auction 9984c
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 158860c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 1320c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer 11496c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 3216c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/14 Auction House
+ Assets:Tajer 34678c
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Fees:Auction 2316c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Gruulmorg 1G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Assets:Tajer 59389c
+ Equity:Gold
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/14 Player
+ Assets:Tajer 6G
+ Equity:Gold
+
+2006/03/14 Auction House
+ Expenses:Items 35s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Tajer:Items "Plans: Wildthorn Mail" 1 @ 125s
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Assets:Bids 259c
+ Assets:Bids 45s
+ Assets:Bids 4720c
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Auction House
+ Expenses:Items 8G
+ Assets:Tajer
+
+2006/03/14 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/14 Puldoost
+ Assets:Tajer 8G
+ Expenses:Items
+
+2006/03/14 Auction House
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" 1 {1.25G}
+ Assets:Tajer:Items
+
+2006/03/15 Auction House
+ Assets:Tajer 45s
+ Assets:Tajer 259c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Assets:Tajer 4720c
+ Assets:Bids
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 12542c ; something got lost here
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 2375c
+ Expenses:Fees:Auction -2375c
+ Assets:Gruulmorg
+
+2006/03/15 Auction House
+ Assets:Danell 4c
+ Equity:Gold
+
+2006/03/15 Transfer
+ Assets:Gruulmorg 2c
+ Assets:Danell
+
+2006/03/15 Transfer
+ Assets:Danell 4250c
+ Expenses:Fees:Auction 750c
+ Assets:Gruulmorg -50s
+
+2006/03/15 Post
+ Expenses:Fees:Mail 60c
+ Assets:Danell
+
+2006/03/15 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/15 Post
+ Assets:Wyshona 40s
+ Expenses:Fees:Mail 30c
+ Assets:Danell
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8s
+ Expenses:Fees:Auction 11s
+ Assets:Wyshona
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Beaststalker's Belt" 1 @ 65G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Vendor
+ Assets:Tajer 16744c
+ Assets:Tajer 16640c
+ Equity:Gold
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 772c
+ Expenses:Fees:Auction 544c
+ Expenses:Fees:Auction 444c
+ Expenses:Fees:Auction 432c
+ Expenses:Fees:Auction 204c
+ Assets:Tajer
+
+2006/03/15 Player
+ Assets:Tajer 12s
+ Equity:Gold
+
+2006/03/15 Vendor
+ Assets:Tajer 22s
+ Equity:Gold
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 1G
+ Assets:Tajer
+
+2006/03/15 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Expenses:Fees:Auction 8268c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 21050c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Plans: Mithril Shield Spike" 1 @ 23000c
+ Assets:Tajer
+
+2006/03/15 Auction House
+ Assets:Tajer:Items "Recipe: Elixir of Giant Growth" 1 @ 150s
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 3G
+ Equity:Gold
+
+2006/03/16 Post
+ Expenses:Fees:Mail 90c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 1195768c
+ Assets:Tajer:Items "Beaststalker's Belt" -1 {65G} @ 1195768c
+ Income:Brokering -545768c
+
+2006/03/16 Auction House
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {21050c}
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" 1 {2.3G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1G}
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" 1 {1.5G}
+ Assets:Tajer:Items
+
+2006/03/16 Player
+ Assets:Tajer 4G
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Wyshona 1341s
+ Equity:Gold
+
+2006/03/16 Auction House
+ Assets:Gruulmorg 4c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 4c
+ Expenses:Fees:Mail 120c
+ Assets:Danell
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 24s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 12s
+ Expenses:Fees:Auction 84c
+ Expenses:Fees:Auction 84c
+ Assets:Wyshona
+
+2006/03/16 Crazy Cat Lady
+ Expenses:Items 40s
+ Expenses:Items 40s
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 60c
+ Assets:Danell 5G
+ Assets:Wyshona
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Tajer 20G
+ Assets:Gruulmorg
+
+2006/03/16 Auction House
+ Assets:Tajer:Items "Pulsating Hydra Heart" 1 @ 1G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 936c
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg 30G
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Gruulmorg:Items "Ace of Warlords" 2 @ 15G
+ Assets:Gruulmorg
+
+2006/03/16 Transfer
+ Assets:Tajer:Items "Ace of Warlords" 2 {15G}
+ Assets:Gruulmorg:Items
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 120c
+ Assets:Tajer
+
+2006/03/16 Auction House
+ Assets:Tajer 2104c
+ Equity:Gold
+
+2006/03/16 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/16 Transfer
+ Assets:Danell 6c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Gruulmorg
+
+2006/03/16 Post
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/16 General Goods Vendor
+ Expenses:Items 50c ; wrapping paper
+ Assets:Tajer
+
+2006/03/16 Player
+ Assets:Tajer 1G
+ Equity:Gold
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1.5G} @ 180584c
+ Income:Brokering -165584c
+
+2006/03/17 Auction House
+ Assets:Wyshona 180584c
+ Assets:Wyshona:Items "Recipe: Elixir of Giant Growth" -1 {1G} @ 180584c
+ Income:Brokering -170584c
+
+2006/03/17 Post
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Player: raev
+ Assets:Tajer:Items "Wildheart Belt" 1 {30G}
+ Assets:Tajer:Items "Ace of Warlords" -2 {15G}
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 7482c
+ Assets:Tajer
+
+2006/03/17 Post
+ Expenses:Fees:Mail 300c
+ Assets:Wyshona
+
+2006/03/17 Player
+ Assets:Wyshona 1G
+ Assets:Wyshona:Items "Plans: Wildthorn Mail" -1 {1.25G} @ 1G
+ Expenses:Capital Loss 25s
+
+2006/03/17 Auction House (implicit transfer)
+ Expenses:Items 279s ; Recipe: Swiftness Potion
+ Assets:Wyshona
+
+2006/03/17 Auction House (implicit transfer)
+ Assets:Danell:Items "Ace of Warlords" 1 @ 3G
+ Assets:Tajer:Items "Ace of Warlords" 1 @ 3.9G
+ Assets:Tajer:Items "Holy Bologna" 1 @ 2G
+ Assets:Tajer:Items "The Emerald Dream" 1 @ 4G
+ Assets:Tajer:Items "The Arcanist's Cookbook" 1 @ 4G
+ Assets:Tajer:Items "Harnessing Shadows" 1 @ 5G
+ Assets:Tajer:Items "Garona: Book on Treachery" 1 @ 4G
+ Assets:Tajer:Items "Preserved Holly" 5 @ 20s
+ Assets:Wyshona
+
+2006/03/17 Auction House
+ Assets:Tajer 4G
+ Assets:Tajer:Items "Pulsating Hydra Heart" -1 {1G} @ 4G
+ Income:Brokering -3G
+
+2006/03/17 Auction House
+ Assets:Danell 3171c
+ Assets:Danell:Items "Ace of Warlords" -1 {3G} @ 3171c
+ Expenses:Capital Loss 26829c
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 12537c
+ Assets:Danell
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 15G
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/17 Auction House
+ Assets:Wyshona 362450c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {21050c} @ 181225c
+ Assets:Wyshona:Items "Plans: Mithril Shield Spike" -1 {2.3G} @ 181225c
+ Income:Brokering -318400c
+
+2006/03/17 Transfer
+ Assets:Danell 499560c
+ Expenses:Gifts 1G
+ Expenses:Fees:Mail 30c
+ Assets:Wyshona
+
+2006/03/17 Post
+ Expenses:Fees:Mail 90c
+ Expenses:Fees:Auction 166c
+ Assets:Gruulmorg
+
+2006/03/17 Transfer
+ Assets:Gruulmorg 459211c
+ Expenses:Fees:Auction 81023c
+ Assets:Danell -540234c
+
+2006/03/17 Transfer
+ Assets:Tajer 662465c
+ Expenses:Fees:Mail 30c
+ Assets:Gruulmorg
+
+2006/03/17 Auction House
+ Expenses:Fees:Auction 75s
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/18 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "Ace of Warlords" -1 {3.9G} @ 15G
+ Income:Brokering -111000c
+
+2006/03/18 Auction House
+ Assets:Tajer 434472c
+ Assets:Tajer:Items "Wildheart Belt" -1 {30G} @ 434472c
+ Income:Brokering -134472c
+
+2006/03/18 Auction House
+ Assets:Tajer 1995s
+ Assets:Tajer:Items "Harnessing Shadows" -1 {5G} @ 1995s
+ Income:Brokering -1495s
+
+2006/03/19 Auction House
+ Assets:Tajer 2850s
+ Assets:Tajer:Items "Garona: Book on Treachery" -1 {4G} @ 2850s
+ Income:Brokering -2450s
+
+2006/03/19 Auction House
+ Assets:Tajer 1710s
+ Assets:Tajer:Items "The Arcanist's Cookbook" -1 {4G} @ 1710s
+ Income:Brokering -1310s
+
+2006/03/19 Auction House
+ Assets:Tajer 46550c
+ Assets:Tajer:Items "Preserved Holly" -5 {20s} @ 9310c
+ Income:Brokering -36550c
+
+2006/03/19 Auction House
+ Assets:Tajer:Items "Two of Portals" 1 @ 3G
+ Assets:Tajer:Items "Two of Portals" 1 @ 2.5G
+ Assets:Tajer
+
+2006/03/20 Auction House
+ Assets:Tajer 163443c
+ Assets:Tajer:Items "Holy Bologna" -1 {2G} @ 163443c
+ Income:Brokering -143443c
+
+2006/03/20 Auction House
+ Assets:Tajer 5G
+ Assets:Tajer:Items "Two of Portals" -1 {3G} @ 5G
+ Income:Brokering -2G
+
+2006/03/20 Auction House
+ Assets:Tajer 15G
+ Assets:Tajer:Items "The Emerald Dream" -1 {4G} @ 15G
+ Income:Brokering -11G
+
+2006/03/20 Auction House
+ Expenses:Fees:Mail 60c
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 170G
+ Assets:Tajer
+
+2006/03/21 Auction House
+ Expenses:Fees:Auction 2760c
+ Expenses:Fees:Auction 2760c
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Assets:Tajer:Items "Nightblade" 1 @ 200G
+ Assets:Tajer
+
+2006/03/22 Auction House
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 177s
+ Expenses:Fees:Auction 75s
+ Assets:Tajer
+
+2006/03/23 Auction House
+ Assets:Tajer 1665260c
+ Assets:Tajer:Items "Orb of Deception" -1 {170G} @ 1665260c
+ Expenses:Capital Loss 34740c
+
+2006/03/26 Auction House
+ Assets:Tajer 81980c
+ Assets:Tajer:Items "Two of Portals" -1 {2.5G} @ 81980c
+ Income:Brokering -56980c
+
+2006/03/26 Player
+ Expenses:Items 150s ; Recipe: Elixir of Minor Agility
+ Expenses:Fees:Mail 30c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/27 Player
+ Assets:Tajer 160G
+ Assets:Tajer:Items "Nightblade" -1 {200G} @ 160G
+ Expenses:Capital Loss 40G
+
+2006/03/27 Player
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/03/26 Player
+ Expenses:Items (9G * 6) ; Traveler's backpacks
+ Expenses:Items 10G
+ Expenses:Fees:Bank 10G
+ Expenses:Fees:Mail 630c
+ Expenses:Fees:Mail 330c
+ Expenses:Fees:Mail 30c
+ Assets:Tajer
+
+2006/04/01 Auction House
+ Assets:Tajer:Items "Orb of Deception" 1 @ 155G
+ Assets:Tajer
diff --git a/test/manual/transaction-codes-1.test b/test/manual/transaction-codes-1.test
new file mode 100644
index 00000000..878c5cac
--- /dev/null
+++ b/test/manual/transaction-codes-1.test
@@ -0,0 +1,22 @@
+reg --columns=60 food and code xfer
+<<<
+2009/10/29 (XFER) Panera Bread
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/10/30 (DEP) Pay day!
+ Assets:Checking $20.00
+ Income
+
+2009/10/30 (XFER) Panera Bread
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/10/31 (559385768438A8D7) Panera Bread
+ Expenses:Food $4.50
+ Liabilities:Credit Card
+>>>1
+09-Oct-29 Panera Bread Expenses:Food $4.50 $4.50
+09-Oct-30 Panera Bread Expenses:Food $4.50 $9.00
+>>>2
+=== 0
diff --git a/test/manual/transaction-codes-2.test b/test/manual/transaction-codes-2.test
new file mode 100644
index 00000000..140044d3
--- /dev/null
+++ b/test/manual/transaction-codes-2.test
@@ -0,0 +1,24 @@
+bal checking --account=code
+<<<
+2009/10/29 (XFER) Panera Bread
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/10/30 (DEP) Pay day!
+ Assets:Checking $20.00
+ Income
+
+2009/10/30 (XFER) Panera Bread
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/10/31 (559385768438A8D7) Panera Bread
+ Expenses:Food $4.50
+ Liabilities:Credit Card
+>>>1
+ $20.00 DEP
+ $-9.00 XFER
+--------------------
+ $11.00
+>>>2
+=== 0
diff --git a/test/manual/transaction-notes-1.test b/test/manual/transaction-notes-1.test
new file mode 100644
index 00000000..d3fab3b6
--- /dev/null
+++ b/test/manual/transaction-notes-1.test
@@ -0,0 +1,24 @@
+reg --columns=60 food and note eat
+<<<
+2009/11/01 Panera Bread ; Got something to eat
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Coffee
+ ; Let’s see, I ate a whole bunch of stuff, drank some coffee,
+ ; pondered a bagel, then decided against the donut.
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Dining
+ ; :Eating:
+ ; This is another long note, after the metadata.
+ Expenses:Food $4.50
+ Assets:Checking
+>>>1
+09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50
+09-Nov-01 Panera Bread Expenses:Food $4.50 $9.00
+>>>2
+=== 0
diff --git a/test/manual/transaction-notes-2.test b/test/manual/transaction-notes-2.test
new file mode 100644
index 00000000..b7a258e0
--- /dev/null
+++ b/test/manual/transaction-notes-2.test
@@ -0,0 +1,23 @@
+reg --columns=60 food and tag eating
+<<<
+2009/11/01 Panera Bread ; Got something to eat
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Coffee
+ ; Let’s see, I ate a whole bunch of stuff, drank some coffee,
+ ; pondered a bagel, then decided against the donut.
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Dining
+ ; :Eating:
+ ; This is another long note, after the metadata.
+ Expenses:Food $4.50
+ Assets:Checking
+>>>1
+09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50
+>>>2
+=== 0
diff --git a/test/manual/transaction-notes-3.test b/test/manual/transaction-notes-3.test
new file mode 100644
index 00000000..9d532d5f
--- /dev/null
+++ b/test/manual/transaction-notes-3.test
@@ -0,0 +1,23 @@
+reg --columns=60 food and tag type=dining
+<<<
+2009/11/01 Panera Bread ; Got something to eat
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Coffee
+ ; Let’s see, I ate a whole bunch of stuff, drank some coffee,
+ ; pondered a bagel, then decided against the donut.
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Dining
+ ; :Eating:
+ ; This is another long note, after the metadata.
+ Expenses:Food $4.50
+ Assets:Checking
+>>>1
+09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50
+>>>2
+=== 0
diff --git a/test/manual/transaction-notes-4.test b/test/manual/transaction-notes-4.test
new file mode 100644
index 00000000..3dd82677
--- /dev/null
+++ b/test/manual/transaction-notes-4.test
@@ -0,0 +1,27 @@
+bal food and tag type --account='"Tags:" + tag("Type")'
+<<<
+2009/11/01 Panera Bread ; Got something to eat
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Coffee
+ ; Let’s see, I ate a whole bunch of stuff, drank some coffee,
+ ; pondered a bagel, then decided against the donut.
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Dining
+ ; :Eating:
+ ; This is another long note, after the metadata.
+ Expenses:Food $4.50
+ Assets:Checking
+>>>1
+ $9.00 Tags
+ $4.50 Coffee
+ $4.50 Dining
+--------------------
+ $9.00
+>>>2
+=== 0
diff --git a/test/manual/transaction-status-1.test b/test/manual/transaction-status-1.test
new file mode 100644
index 00000000..4bdf893a
--- /dev/null
+++ b/test/manual/transaction-status-1.test
@@ -0,0 +1,19 @@
+reg --columns=60 food
+<<<
+2009/10/31 * Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/01 ! Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/02 Panera Bread
+ Expenses:Food $4.50
+ Assets
+>>>1
+09-Oct-31 Panera Bread Expenses:Food $4.50 $4.50
+09-Nov-01 Panera Bread Expenses:Food $4.50 $9.00
+09-Nov-02 Panera Bread Expenses:Food $4.50 $13.50
+>>>2
+=== 0
diff --git a/test/manual/transaction-status-2.test b/test/manual/transaction-status-2.test
new file mode 100644
index 00000000..dbbb04ae
--- /dev/null
+++ b/test/manual/transaction-status-2.test
@@ -0,0 +1,17 @@
+reg --columns=60 food --cleared
+<<<
+2009/10/31 * Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/01 ! Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/02 Panera Bread
+ Expenses:Food $4.50
+ Assets
+>>>1
+09-Oct-31 Panera Bread Expenses:Food $4.50 $4.50
+>>>2
+=== 0
diff --git a/test/manual/transaction-status-3.test b/test/manual/transaction-status-3.test
new file mode 100644
index 00000000..1e6467ef
--- /dev/null
+++ b/test/manual/transaction-status-3.test
@@ -0,0 +1,18 @@
+reg --columns=60 food --uncleared
+<<<
+2009/10/31 * Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/01 ! Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/02 Panera Bread
+ Expenses:Food $4.50
+ Assets
+>>>1
+09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50
+09-Nov-02 Panera Bread Expenses:Food $4.50 $9.00
+>>>2
+=== 0
diff --git a/test/manual/transaction-status-4.test b/test/manual/transaction-status-4.test
new file mode 100644
index 00000000..5275eec3
--- /dev/null
+++ b/test/manual/transaction-status-4.test
@@ -0,0 +1,17 @@
+reg --columns=60 food --pending
+<<<
+2009/10/31 * Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/01 ! Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/02 Panera Bread
+ Expenses:Food $4.50
+ Assets
+>>>1
+09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50
+>>>2
+=== 0
diff --git a/test/prove.sh b/test/prove.sh
new file mode 100755
index 00000000..5dadca71
--- /dev/null
+++ b/test/prove.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if [ -n "$1" ]; then
+ ledger --seed=$1 --actual --args-only generate > /tmp/cout
+else
+ ledger --actual --args-only generate > /tmp/cout
+fi
+
+ledger -f /tmp/cout --actual --args-only print > /tmp/print
+
+diff -w -U3 /tmp/cout /tmp/print
diff --git a/test/regress/04C5E1CA.test b/test/regress/04C5E1CA.test
new file mode 100644
index 00000000..729ae6bf
--- /dev/null
+++ b/test/regress/04C5E1CA.test
@@ -0,0 +1,18 @@
+reg
+<<<
+2009/04/04 CS Club Sign
+ Expenses:School:CS Club:Home Depot:4" Brush 2 @ $3.97
+ Liabilities:Mastercard
+
+2009/04/04 CS Club Sign
+ Expenses:School:CS Club:Home Depot:4" Brush (2 * $3.97)
+ Liabilities:Mastercard
+>>>1
+09-Apr-04 CS Club Sign Ex:Sc:CS:Ho:4" Brush 2 2
+ Liabilities:Mastercard $-7.94 2
+ $-7.94
+09-Apr-04 CS Club Sign Ex:Sc:CS:Ho:4" Brush $7.94 2
+ Liabilities:Mastercard $-7.94 2
+ $-7.94
+>>>2
+=== 0
diff --git a/test/regress/0CA014F9.test b/test/regress/0CA014F9.test
new file mode 100644
index 00000000..d3377132
--- /dev/null
+++ b/test/regress/0CA014F9.test
@@ -0,0 +1,13 @@
+bal
+<<<
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+>>>1
+ 0.350 VMMXX Assets:Investments:Vanguard:VMMXX
+ $-0.35 Income:Dividends:Vanguard:VMMXX
+--------------------
+ $-0.35
+ 0.350 VMMXX
+>>>2
+=== 0
diff --git a/test/regress/13965214.test b/test/regress/13965214.test
new file mode 100644
index 00000000..674d4d7d
--- /dev/null
+++ b/test/regress/13965214.test
@@ -0,0 +1,30 @@
+reg
+<<<
+Y2008
+
+01/30 A
+ Bank 130
+ Income
+
+02/01 B
+ Bank 140
+ Income
+
+02/20 C
+ Bank 150
+ Income
+
+03/01 D
+ Bank 160
+ Income
+>>>1
+08-Jan-30 A Bank 130 130
+ Income -130 0
+08-Feb-01 B Bank 140 140
+ Income -140 0
+08-Feb-20 C Bank 150 150
+ Income -150 0
+08-Mar-01 D Bank 160 160
+ Income -160 0
+>>>2
+=== 0
diff --git a/test/regress/1CF1EEC2.test b/test/regress/1CF1EEC2.test
new file mode 100644
index 00000000..f97eea81
--- /dev/null
+++ b/test/regress/1CF1EEC2.test
@@ -0,0 +1,27 @@
+equity assets
+<<<
+2009/01/01 sample
+ Assets:Super:ARF $1000.00
+ Assets:Super:CSS $1000.00
+ Assets:Super:CSS:Contributions $1000.00
+ Income:Opening Balances
+
+2009/02/01 sample
+ Assets:Super:ARF $1000.00
+ Assets:Super:CSS $1000.00
+ Assets:Super:CSS:Contributions $1000.00
+ Income:Opening Balances
+
+2009/03/01 sample
+ Assets:Super:ARF $1000.00
+ Assets:Super:CSS $1000.00
+ Assets:Super:CSS:Contributions $1000.00
+ Income:Opening Balances
+>>>1
+2009/03/01 Opening Balances
+ Assets:Super:ARF $3000.00
+ Assets:Super:CSS $3000.00
+ Assets:Super:CSS:Contributions $3000.00
+ Equity:Opening Balances $-9000.00
+>>>2
+=== 0
diff --git a/test/regress/25A099C9.test b/test/regress/25A099C9.test
new file mode 100644
index 00000000..4067d005
--- /dev/null
+++ b/test/regress/25A099C9.test
@@ -0,0 +1,19 @@
+-f $sourcepath/src/amount.h reg
+<<<
+>>>1
+>>>2
+While parsing file "$sourcepath/src/amount.h", line 67:
+Error: No quantity specified for amount
+While parsing file "$sourcepath/src/amount.h", line 720:
+Error: Invalid date/time: line amount_t amoun
+While parsing file "$sourcepath/src/amount.h", line 726:
+Error: Invalid date/time: line string amount_
+While parsing file "$sourcepath/src/amount.h", line 732:
+Error: Invalid date/time: line string amount_
+While parsing file "$sourcepath/src/amount.h", line 738:
+Error: Invalid date/time: line string amount_
+While parsing file "$sourcepath/src/amount.h", line 744:
+Error: Invalid date/time: line std::ostream&
+While parsing file "$sourcepath/src/amount.h", line 751:
+Error: Invalid date/time: line std::istream&
+=== 7
diff --git a/test/regress/2E3496BD.test b/test/regress/2E3496BD.test
new file mode 100644
index 00000000..cb105f08
--- /dev/null
+++ b/test/regress/2E3496BD.test
@@ -0,0 +1,20 @@
+bal
+<<<
+D 1,000.00 USD
+
+2007-12-31 * Start of year / Opening balances.
+ Account1 1000 EUR @ 1.6 USD
+ Account2 -1000 EUR @ 1.5 USD
+>>>1
+>>>2
+While parsing file "$FILE", line 5:
+While balancing transaction from "$FILE", lines 3-5:
+> 2007-12-31 * Start of year / Opening balances.
+> Account1 1000 EUR @ 1.6 USD
+> Account2 -1000 EUR @ 1.5 USD
+Unbalanced remainder is:
+ 100.00 USD
+Amount to balance against:
+ 1,600.0 USD
+Error: Transaction does not balance
+=== 1
diff --git a/test/regress/373540CC.test b/test/regress/373540CC.test
new file mode 100644
index 00000000..5c589ec9
--- /dev/null
+++ b/test/regress/373540CC.test
@@ -0,0 +1,9 @@
+bal --sort total --flat -X '$' not '(Income|Liabilities)'
+<<<
+2004/05/27 Book Store
+ Expenses:Books 20 BOOK @ $10
+ Liabilities:MasterCard $-200.00
+>>>1
+ $200.00 Expenses:Books
+>>>2
+=== 0
diff --git a/test/regress/3AB70168.test b/test/regress/3AB70168.test
new file mode 100644
index 00000000..6c08b0bf
--- /dev/null
+++ b/test/regress/3AB70168.test
@@ -0,0 +1,13 @@
+bal
+<<<
+i 2007/03/01 23:00:00 A
+o 2007/03/02 01:00:00
+i 2007/03/11 23:00:00 B
+o 2007/03/12 01:00:00
+>>>1
+ 2.0h A
+ 2.0h B
+--------------------
+ 4.0h
+>>>2
+=== 0
diff --git a/test/regress/461980A1.test b/test/regress/461980A1.test
new file mode 100644
index 00000000..bbf2ee4e
--- /dev/null
+++ b/test/regress/461980A1.test
@@ -0,0 +1,13 @@
+bal
+<<<
+2008/01/01 one
+ test:a 1
+ test:b
+>>>1
+ 0 test
+ 1 a
+ -1 b
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/regress/55831A79.test b/test/regress/55831A79.test
new file mode 100644
index 00000000..d553bdfa
--- /dev/null
+++ b/test/regress/55831A79.test
@@ -0,0 +1,26 @@
+bal discover
+<<<
+2008/01/01 * previous balances
+ liabilities:credit cards:discover 4462 $-1094.38
+ equity:opening balances
+
+2008/01/18 * DISCOVER FEES
+ liabilities:credit cards:discover 4462:interest $-36.59
+ assets:bank:wells fargo:checking
+
+2008/01/18 * DISCOVER FEES
+ liabilities:credit cards:discover 4462:fee $-39
+ liabilities:credit cards:discover 4462:interest $-28.17
+ assets:bank:wells fargo:checking
+
+2008/03/01 * discover card payment
+ liabilities:credit cards:discover 4462 $1198.14
+ assets:bank:wells fargo:checking
+>>>1
+ 0 liabilities:credit cards:discover 4462
+ $-39.00 fee
+ $-64.76 interest
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/regress/5A03CFC3.test b/test/regress/5A03CFC3.test
new file mode 100644
index 00000000..440ff960
--- /dev/null
+++ b/test/regress/5A03CFC3.test
@@ -0,0 +1,72 @@
+bal assets
+<<<
+= /^Income/
+ (Liabilities:Tithe) 0.12
+
+~ Monthly
+ Assets:Checking $500.00
+ Income:Salary
+
+2003/12/01 * Checking balance
+ Assets:Checking $1,000.00
+ Equity:Opening Balances
+
+2003/12/20 Organic Co-op
+ Expenses:Food:Groceries $ 37.50 ; [=2004/01/01]
+ Expenses:Food:Groceries $ 37.50 ; [=2004/02/01]
+ Expenses:Food:Groceries $ 37.50 ; [=2004/03/01]
+ Expenses:Food:Groceries $ 37.50 ; [=2004/04/01]
+ Expenses:Food:Groceries $ 37.50 ; [=2004/05/01]
+ Expenses:Food:Groceries $ 37.50 ; [=2004/06/01]
+ Assets:Checking $ -225.00
+
+2003/12/28=2004/01/01 Acme Mortgage
+ Liabilities:Mortgage:Principal $ 200.00
+ Expenses:Interest:Mortgage $ 500.00
+ Expenses:Escrow $ 300.00
+ Assets:Checking $ -1000.00
+
+2004/01/02 Grocery Store
+ Expenses:Food:Groceries $ 65.00
+ Assets:Checking
+
+2004/01/05 Employer
+ Assets:Checking $ 2000.00
+ Income:Salary
+
+2004/01/14 Bank
+ ; Regular monthly savings transfer
+ Assets:Savings $ 300.00
+ Assets:Checking
+
+2004/01/19 Grocery Store
+ Expenses:Food:Groceries $ 44.00
+ Assets:Checking
+
+2004/01/25 Bank
+ ; Transfer to cover car purchase
+ Assets:Checking $ 5,500.00
+ Assets:Savings
+ ; :nobudget:
+
+2004/01/25 Tom's Used Cars
+ Expenses:Auto $ 5,500.00
+ ; :nobudget:
+ Assets:Checking
+
+2004/01/27 Book Store
+ Expenses:Books $20.00
+ Liabilities:MasterCard
+
+2004/02/01 Sale
+ Assets:Checking:Business $ 30.00
+ Income:Sales
+>>>1
+ $ -3,804.00 Assets
+ $ 1,396.00 Checking
+ $ 30.00 Business
+ $ -5,200.00 Savings
+--------------------
+ $ -3,804.00
+>>>2
+=== 0
diff --git a/test/regress/5F1BAF17.test b/test/regress/5F1BAF17.test
new file mode 100644
index 00000000..f52ffb86
--- /dev/null
+++ b/test/regress/5F1BAF17.test
@@ -0,0 +1,130 @@
+bal da39 --flat --sort amount --display-total amount
+<<<
+2006/02/16 b5f40e96
+ da39a3ee:8d437dbf:ee2bf9bd:f61e33bf $713.35
+ Assets
+
+2006/03/27 c7ab1f2d
+ da39a3ee:8d437dbf:ee2bf9bd:9b69a35a $139.62
+ Assets
+
+2006/03/30 f32ea1dc
+ da39a3ee:8d437dbf:ee2bf9bd:d219c681 $1,600.00
+ Assets
+
+2006/04/21 d449d51e
+ da39a3ee:8d437dbf:ee2bf9bd:75b04b88 $698.10
+ Assets
+
+2006/05/02 b02f8323
+ da39a3ee:8d437dbf:ee2bf9bd $42.22
+ Assets
+
+2006/05/05 2a6f6850
+ da39a3ee:8d437dbf:ee2bf9bd:75b04b88:b3850e04 $2,468.00
+ Assets
+
+2006/05/09 59f92263
+ da39a3ee:8d437dbf:ee2bf9bd:071c929a $132.82
+ Assets
+
+2006/05/18 f78a7a51
+ da39a3ee:8d437dbf:ee2bf9bd:e97de844 $368.05
+ Assets
+
+2006/05/19 f35c594c
+ da39a3ee:8d437dbf:ee2bf9bd:d4e7d7d3 $386.62
+ Assets
+
+2006/05/22 0233a991
+ da39a3ee:8d437dbf:ee2bf9bd:9c6e5a3f $141.98
+ Assets
+
+2006/05/23 56ccae7f
+ da39a3ee:8d437dbf:ee2bf9bd:d31d367b $81.78
+ Assets
+
+2006/05/24 d449d51e
+ da39a3ee:8d437dbf:ee2bf9bd:75b04b88 $65.00
+ Assets
+
+2006/05/25 dc833c91
+ da39a3ee:8d437dbf:ee2bf9bd:d31d367b $34.37
+ Assets
+
+2006/05/31 6822b496
+ da39a3ee:8d437dbf:ee2bf9bd:e97de844 $41.78
+ Assets
+
+2006/06/02 dff8ccb2
+ da39a3ee:8d437dbf:ee2bf9bd:14e351e1 $67.36
+ Assets
+
+2006/06/02 e1eb3f4b
+ da39a3ee:8d437dbf:ee2bf9bd:2c7a078f $14.00
+ Assets
+
+2006/06/04 feec73ea
+ da39a3ee:8d437dbf:ee2bf9bd:131260cb $144.99
+ Assets
+
+2006/06/04 e8f65e0a
+ da39a3ee:8d437dbf:ee2bf9bd:d219c681 $75.00
+ Assets
+
+2006/06/04 3fd43f7b
+ da39a3ee:8d437dbf:ee2bf9bd:9c4ba7d0 $239.59
+ Assets
+
+2006/06/06 754be754
+ da39a3ee:8d437dbf:ee2bf9bd:35b25929 $1,160.14
+ Assets
+
+2006/06/06 00c16d44
+ da39a3ee:8d437dbf:ee2bf9bd:e97de844 $78.45
+ Assets
+
+2006/06/08 e7b0b317
+ da39a3ee:8d437dbf:ee2bf9bd $443.00
+ Assets
+
+2006/07/17 a30c4c31
+ da39a3ee:8d437dbf:ee2bf9bd $880.80
+ Assets
+
+2006/08/08 e31a0cf9
+ da39a3ee:8d437dbf:ee2bf9bd $104.53
+ Assets
+
+2006/08/10 f0c0c688
+ da39a3ee:8d437dbf:ee2bf9bd $196.70
+ Assets
+
+2006/09/12 1bc59c63
+ da39a3ee:8d437dbf:ee2bf9bd $217.79
+ Assets
+
+2007/07/16 557e3a00
+ da39a3ee:8d437dbf:ee2bf9bd:f61e33bf $117.80
+ Assets
+>>>1
+ $14.00 da39a3ee:8d437dbf:ee2bf9bd:2c7a078f
+ $67.36 da39a3ee:8d437dbf:ee2bf9bd:14e351e1
+ $116.15 da39a3ee:8d437dbf:ee2bf9bd:d31d367b
+ $132.82 da39a3ee:8d437dbf:ee2bf9bd:071c929a
+ $139.62 da39a3ee:8d437dbf:ee2bf9bd:9b69a35a
+ $141.98 da39a3ee:8d437dbf:ee2bf9bd:9c6e5a3f
+ $144.99 da39a3ee:8d437dbf:ee2bf9bd:131260cb
+ $239.59 da39a3ee:8d437dbf:ee2bf9bd:9c4ba7d0
+ $386.62 da39a3ee:8d437dbf:ee2bf9bd:d4e7d7d3
+ $488.28 da39a3ee:8d437dbf:ee2bf9bd:e97de844
+ $763.10 da39a3ee:8d437dbf:ee2bf9bd:75b04b88
+ $831.15 da39a3ee:8d437dbf:ee2bf9bd:f61e33bf
+ $1,160.14 da39a3ee:8d437dbf:ee2bf9bd:35b25929
+ $1,675.00 da39a3ee:8d437dbf:ee2bf9bd:d219c681
+ $1,885.04 da39a3ee:8d437dbf:ee2bf9bd
+ $2,468.00 da39a3ee:8d437dbf:ee2bf9bd:75b04b88:b3850e04
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/regress/5FBF2ED8.test b/test/regress/5FBF2ED8.test
new file mode 100644
index 00000000..78df5a6e
--- /dev/null
+++ b/test/regress/5FBF2ED8.test
@@ -0,0 +1,20 @@
+bal -B
+<<<
+2008/01/01 * Checking balance
+ Assets:Bank:Checking £0.00
+ Equity:Opening Balances
+
+2008/02/02 Salary
+ Income:Employer £-334.00
+ Assets:Bank:Checking $512.85 @@ £334.00
+
+2008/03/02 Salary
+ Income:Employer £-248.07
+ Assets:Bank:Checking $404.82 @@ £248.07
+>>>1
+ £582.07 Assets:Bank:Checking
+ £-582.07 Income:Employer
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/regress/647D5DB9.test b/test/regress/647D5DB9.test
new file mode 100644
index 00000000..2d6b78e3
--- /dev/null
+++ b/test/regress/647D5DB9.test
@@ -0,0 +1,17 @@
+bal --end 2008/12/31 -JV Equities
+<<<
+2008/01/01 * Purchase Apple shares
+ Equities 1000 AAPL @ $2
+ Cash
+
+2008/06/30 * Sell some Apple shares
+ Equities -500 AAPL @ $2.5
+ Cash
+
+P 2008/10/01 02:18:02 AAPL $3
+P 2009/01/31 02:18:02 AAPL $4
+P 3000/01/01 02:18:02 APPL $100
+>>>1
+2008-12-31 1500
+>>>2
+=== 0
diff --git a/test/regress/6DAB9FE3.test b/test/regress/6DAB9FE3.test
new file mode 100644
index 00000000..50b944ae
--- /dev/null
+++ b/test/regress/6DAB9FE3.test
@@ -0,0 +1,10 @@
+reg -E
+<<<
+2009/01/01 Sample
+ assets 0 FOO @ $8.88
+ equity
+>>>1
+09-Jan-01 Sample assets 0 0
+ equity 0 0
+>>>2
+=== 0
diff --git a/test/regress/727B2DF8.test b/test/regress/727B2DF8.test
new file mode 100644
index 00000000..a13e8292
--- /dev/null
+++ b/test/regress/727B2DF8.test
@@ -0,0 +1,81 @@
+reg --color --force-color
+<<<
+N $
+
+= /^Expenses:Books/
+ (Liabilities:Taxes) -0.10
+
+~ Monthly
+ Assets:Bank:Checking $500.00
+ Income:Salary
+
+2004/05/01 * Checking balance
+ Assets:Bank:Checking $1,000.00
+ Equity:Opening Balances
+
+2004/05/03=2004/05/01 * Investment balance
+ Assets:Brokerage 50 AAPL @ $30.00
+ Equity:Opening Balances
+
+2004/05/14 * Páy dày
+ Assets:Bank:Checking 500.00€
+ Income:Salary
+
+2004/05/14 * Another dày in which there is Páying
+ Asséts:Bánk:Chécking:Asséts:Bánk:Chécking $500.00
+ Income:Salary
+
+2004/05/14 * Another dày in which there is Páying
+ РуÑÑкий Ñзык:РуÑÑкий Ñзык:РуÑÑкий Ñзык:РуÑÑкий Ñзык $1000.00
+ Income:Salary
+
+2004/05/27 Book Store
+ Expenses:Books $20.00
+ Expenses:Cards $40.00
+ Expenses:Docs $30.00
+ Liabilities:MasterCard
+
+2004/05/27 (100) Credit card company
+ ; This is an xact note!
+ ; Sample: Value
+ Liabilities:MasterCard $20.00
+ ; This is a posting note!
+ ; Sample: Another Value
+ ; :MyTag:
+ Assets:Bank:Checking
+ ; :AnotherTag:
+>>>1
+04-May-01 Checking balance Assets:Bank:Checking  $1,000.00 $1,000.00
+ Eq:Opening Balances  $-1,000.00 0
+04-May-03 Investment balance Assets:Brokerage  50 AAPL 50 AAPL
+ Eq:Opening Balances  $-1,500.00 $-1,500.00
+ 50 AAPL
+04-May-14 Páy dày Assets:Bank:Checking  500.00€ $-1,500.00
+ 50 AAPL
+ 500.00€
+ Income:Salary  -500.00€ $-1,500.00
+ 50 AAPL
+04-May-14 Another dày in whic.. ..Bá:Ch:As:Bá:Chécking $500.00 $-1,000.00
+ 50 AAPL
+ Income:Salary  $-500.00 $-1,500.00
+ 50 AAPL
+04-May-14 Another dày in whic.. Ру:Ру:Ру:РуÑÑкий Ñзык  $1,000.00 $-500.00
+ 50 AAPL
+ Income:Salary  $-1,000.00 $-1,500.00
+ 50 AAPL
+04-May-27 Book Store  Expenses:Books  $20.00 $-1,480.00
+ 50 AAPL
+ Expenses:Cards  $40.00 $-1,440.00
+ 50 AAPL
+ Expenses:Docs  $30.00 $-1,410.00
+ 50 AAPL
+ Liabilities:MasterCard $-90.00 $-1,500.00
+ 50 AAPL
+ (Liabilities:Taxes)  $-2.00 $-1,502.00
+ 50 AAPL
+04-May-27 Credit card company  Liabilities:MasterCard $20.00 $-1,482.00
+ 50 AAPL
+ Assets:Bank:Checking  $-20.00 $-1,502.00
+ 50 AAPL
+>>>2
+=== 0
diff --git a/test/regress/793F6BF0.test b/test/regress/793F6BF0.test
new file mode 100644
index 00000000..059bd9b6
--- /dev/null
+++ b/test/regress/793F6BF0.test
@@ -0,0 +1,52 @@
+entry 2009/03/15 book 10
+<<<
+N $
+
+= /^Expenses:Books/
+ (Liabilities:Taxes) -0.10
+
+~ Monthly
+ Assets:Bank:Checking $500.00
+ Income:Salary
+
+2004/05/01 * Checking balance
+ Assets:Bank:Checking $1,000.00
+ Equity:Opening Balances
+
+2004/05/03=2004/05/01 * Investment balance
+ Assets:Brokerage 50 AAPL @ $30.00
+ Equity:Opening Balances
+
+2004/05/14 * Páy dày
+ Assets:Bank:Checking 500.00€
+ Income:Salary
+
+2004/05/14 * Another dày in which there is Páying
+ Asséts:Bánk:Chécking:Asséts:Bánk:Chécking $500.00
+ Income:Salary
+
+2004/05/14 * Another dày in which there is Páying
+ РуÑÑкий Ñзык:РуÑÑкий Ñзык:РуÑÑкий Ñзык:РуÑÑкий Ñзык $1000.00
+ Income:Salary
+
+2004/05/27 Book Store
+ Expenses:Books $20.00
+ Expenses:Cards $40.00
+ Expenses:Docs $30.00
+ Liabilities:MasterCard
+
+2004/05/27 (100) Credit card company
+ ; This is an xact note!
+ ; Sample: Value
+ Liabilities:MasterCard $20.00
+ ; This is a posting note!
+ ; Sample: Another Value
+ ; :MyTag:
+ Assets:Bank:Checking
+ ; :AnotherTag:
+>>>1
+2009/03/15 Book Store
+ Expenses:Books $10.00
+ Liabilities:MasterCard
+>>>2
+=== 0
diff --git a/test/regress/7F3650FD.test b/test/regress/7F3650FD.test
new file mode 100644
index 00000000..f7154eb8
--- /dev/null
+++ b/test/regress/7F3650FD.test
@@ -0,0 +1,95 @@
+period --now=2010/11/01 12/01
+<<<
+>>>1
+--- Period expression tokens ---
+TOK_DATE: month Dec day 1
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: in month Dec day 1
+
+--- After stabilization ---
+ range: in month Dec day 1
+ start: 10-Dec-01
+ finish: 10-Dec-02
+
+--- Sample dates in range (max. 20) ---
+ 1: 10-Dec-01
+>>>2
+=== 0
+period --now=2010/11/01 10/01
+<<<
+>>>1
+--- Period expression tokens ---
+TOK_DATE: month Oct day 1
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: in month Oct day 1
+
+--- After stabilization ---
+ range: in month Oct day 1
+ start: 10-Oct-01
+ finish: 10-Oct-02
+
+--- Sample dates in range (max. 20) ---
+ 1: 10-Oct-01
+>>>2
+=== 0
+period --now=2010/11/01 2009/10
+<<<
+>>>1
+--- Period expression tokens ---
+TOK_DATE: year 2009 month Oct
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: in year 2009 month Oct
+
+--- After stabilization ---
+ range: in year 2009 month Oct
+ start: 09-Oct-01
+ finish: 09-Nov-01
+
+--- Sample dates in range (max. 20) ---
+ 1: 09-Oct-01
+>>>2
+=== 0
+period --now=2010/11/01 2009/10/01
+<<<
+>>>1
+--- Period expression tokens ---
+TOK_DATE: year 2009 month Oct day 1
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: in year 2009 month Oct day 1
+
+--- After stabilization ---
+ range: in year 2009 month Oct day 1
+ start: 09-Oct-01
+ finish: 09-Oct-02
+
+--- Sample dates in range (max. 20) ---
+ 1: 09-Oct-01
+>>>2
+=== 0
+period --now=2010/11/01 2009
+<<<
+>>>1
+--- Period expression tokens ---
+TOK_A_YEAR: 2009
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: in year 2009
+
+--- After stabilization ---
+ range: in year 2009
+ start: 09-Jan-01
+ finish: 10-Jan-01
+
+--- Sample dates in range (max. 20) ---
+ 1: 09-Jan-01
+>>>2
+=== 0
diff --git a/test/regress/8254755E.test b/test/regress/8254755E.test
new file mode 100644
index 00000000..26baf52d
--- /dev/null
+++ b/test/regress/8254755E.test
@@ -0,0 +1,20 @@
+bal --flat food:out
+<<<
+~ Monthly
+ Expenses:Auto:Fuel $120.00
+ Expenses:Food:Out $100.00
+ Expenses:Food:Groceries $350.00
+ Assets
+
+2009/11/01
+ Expenses:Food:Out $50.00
+ Assets
+>>>1
+ $50.00 Expenses:Food:Out
+>>>2
+=== 0
+bal --flat --budget food:out
+>>>1
+ $-50.00 Expenses:Food:Out
+>>>2
+=== 0
diff --git a/test/regress/86D2BDC4.test b/test/regress/86D2BDC4.test
new file mode 100644
index 00000000..8cd51e42
--- /dev/null
+++ b/test/regress/86D2BDC4.test
@@ -0,0 +1,12 @@
+reg -B
+<<<
+2009/06/03 Westjet
+ Expenses:Transportation:Air C$429.80 @ 1.572865
+ Expenses:Bank:Fees 2.73
+ Liabilities:Mastercard
+>>>1
+09-Jun-03 Westjet Ex:Transportation:Air 676.017377 676.017377
+ Expenses:Bank:Fees 2.73 678.747377
+ Liabilities:Mastercard -678.747377 0
+>>>2
+=== 0
diff --git a/test/regress/B68FFB0D.test b/test/regress/B68FFB0D.test
new file mode 100644
index 00000000..2dd2086c
--- /dev/null
+++ b/test/regress/B68FFB0D.test
@@ -0,0 +1,15 @@
+print
+<<<
+D $1,000.00
+
+2009/01/01 Sample
+ assets 134.123 FOO @ $8.88
+ assets 100 BAR @ $8.88
+ equity
+>>>1
+2009/01/01 Sample
+ assets 134.123 FOO @ $8.88
+ assets 100 BAR @ $8.88
+ equity
+>>>2
+=== 0
diff --git a/test/regress/BBFA1759.test b/test/regress/BBFA1759.test
new file mode 100644
index 00000000..cd5990fc
--- /dev/null
+++ b/test/regress/BBFA1759.test
@@ -0,0 +1,20 @@
+period june 2008
+<<<
+>>>1
+--- Period expression tokens ---
+TOK_A_MONTH: Jun
+TOK_A_YEAR: 2008
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: in year 2008 month Jun
+
+--- After stabilization ---
+ range: in year 2008 month Jun
+ start: 08-Jun-01
+ finish: 08-Jul-01
+
+--- Sample dates in range (max. 20) ---
+ 1: 08-Jun-01
+>>>2
+=== 0
diff --git a/test/regress/C523E23F.test b/test/regress/C523E23F.test
new file mode 100644
index 00000000..b8b08e00
--- /dev/null
+++ b/test/regress/C523E23F.test
@@ -0,0 +1,21 @@
+bal
+<<<
+D 1.000,00€
+
+2009/03/16 * denn's
+ ; Kauf: Yogi-Tee
+ Aufwand:Einkauf:Lebensmittel 17,94€
+ Aktiva:Bank:Girokonto
+
+2009/03/24 Ansparen
+ Aktiva:Bank:Sparkonto 800,00€
+ Aktiva:Bank:Girokonto
+>>>1
+ -17,94€ Aktiva:Bank
+ -817,94€ Girokonto
+ 800,00€ Sparkonto
+ 17,94€ Aufwand:Einkauf:Lebensmittel
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/regress/D060256A.test b/test/regress/D060256A.test
new file mode 100644
index 00000000..26c30351
--- /dev/null
+++ b/test/regress/D060256A.test
@@ -0,0 +1,16 @@
+budget --now=2009/11/01 --end=2009/11/30
+<<<
+~ Monthly
+ Expenses:Food $500.00
+ Assets
+
+2009/11/01 Sample
+ Expenses:Food:Dining $20.00
+ Assets
+>>>1
+ $-20.00 $-500.00 $480.00 4% Assets
+ $20.00 $500.00 $-480.00 4% Expenses:Food
+------------ ------------ ------------ -----
+ 0 0 0 0
+>>>2
+=== 0
diff --git a/test/regress/D943AE0F.test b/test/regress/D943AE0F.test
new file mode 100644
index 00000000..94a26df5
--- /dev/null
+++ b/test/regress/D943AE0F.test
@@ -0,0 +1,15 @@
+reg -V --end=2009/06/16
+<<<
+D 1000.00 EUR
+
+2008/04/15 * Paid expenses back from cie.
+ Expenses:Cie-Reimbursements 2000 CAD @ 1.10 EUR
+ Assets:Checking
+
+P 2008/04/20 00:00:00 CAD 1.20 EUR
+>>>1
+08-Apr-15 Paid expenses back .. Ex:Cie-Reimbursements 2200.00 EUR 2200.00 EUR
+ Assets:Checking -2200.00 EUR 0
+09-Jun-16 Commodities revalued <Revalued> 200.00 EUR 200.00 EUR
+>>>2
+=== 0
diff --git a/test/regress/E4C9A8EA.test b/test/regress/E4C9A8EA.test
new file mode 100644
index 00000000..fed47c82
--- /dev/null
+++ b/test/regress/E4C9A8EA.test
@@ -0,0 +1,24 @@
+reg
+<<<
+2007/12/31 * Cost basis for: RED HAT INC RHT
+ Assets:Investments:RBC-Broker:Account-RSP 4 RHT
+ Equity:Opening-Balances:Cost -689.87 CAD
+
+2008/01/03=2007/12/28 * Sell -- RHT -- RED HAT INC CA TAUX DE CHANGE .96590
+ Assets:Investments:RBC-Broker:Account-RSP -4.00 RHT @ 21.14 CAD
+ Expenses:Financial:Commissions 9.95 USD @ 0.96590 CAD
+ Assets:Investments:RBC-Broker:Account-RSP 72.06 CAD
+ Expenses:Financial:Fees
+>>>1
+07-Dec-31 Cost basis for: RED.. As:In:RB:Account-RSP 4.00 RHT 4.00 RHT
+ Eq:Op:Cost -689.87 CAD -689.87 CAD
+ 4.00 RHT
+08-Jan-03 Sell -- RHT -- RED .. As:In:RB:Account-RSP -4.00 RHT -689.87 CAD
+ Ex:Fi:Commissions 9.95 USD -689.87 CAD
+ 9.95 USD
+ As:In:RB:Account-RSP 72.06 CAD -617.81 CAD
+ 9.95 USD
+ Ex:Financial:Fees 2.89 CAD -614.92 CAD
+ 9.95 USD
+>>>2
+=== 0
diff --git a/test/regress/E627C594.test b/test/regress/E627C594.test
new file mode 100644
index 00000000..0dfbf778
--- /dev/null
+++ b/test/regress/E627C594.test
@@ -0,0 +1,18 @@
+reg --forecast-while="d<[2010/03/01]" --now=2009/11/01
+<<<
+~ Monthly
+ Expenses:Food $500.00
+ Assets
+
+2009/11/01 Sample
+ Expenses:Food:Dining $20.00
+ Assets
+>>>1
+09-Nov-01 Sample Expenses:Food:Dining $20.00 $20.00
+ Assets $-20.00 0
+10-Jan-01 Forecast transaction Expenses:Food $500.00 $500.00
+10-Jan-01 Forecast transaction Assets $-500.00 0
+10-Feb-01 Forecast transaction Expenses:Food $500.00 $500.00
+10-Feb-01 Forecast transaction Assets $-500.00 0
+>>>2
+=== 0
diff --git a/test/regress/E9F130C5.test b/test/regress/E9F130C5.test
new file mode 100644
index 00000000..b718b11d
--- /dev/null
+++ b/test/regress/E9F130C5.test
@@ -0,0 +1,30 @@
+bal as
+<<<
+2008/01/01 income
+ assets:bank:checking $1
+ income:salary
+
+2008/06/01 gift
+ assets:bank:checking $1
+ income:gifts
+
+2008/06/02 save
+ assets:bank:saving $1
+ assets:bank:checking
+
+2008/06/03 * eat & shop
+ expenses:food $1
+ expenses:supplies $1
+ assets:cash
+
+2008/12/31 * pay off
+ liabilities:debts $1
+ assets:bank:checking
+>>>1
+ $-1 assets
+ $1 bank:saving
+ $-2 cash
+--------------------
+ $-1
+>>>2
+=== 0
diff --git a/test/regress/F559EC12.test b/test/regress/F559EC12.test
new file mode 100644
index 00000000..c8b686db
--- /dev/null
+++ b/test/regress/F559EC12.test
@@ -0,0 +1,43 @@
+format "%-12(scrub(amount))"
+<<<
+>>>1
+--- Context is first posting of the following transaction ---
+2004/05/27 Book Store
+ ; This note applies to all postings. :SecondTag:
+ Expenses:Books 20 BOOK @ $10
+ ; Metadata: Some Value
+ ; :ExampleTag:
+ ; Here follows a note describing the posting.
+ Liabilities:MasterCard $-200.00
+
+--- Input format string ---
+%-12(scrub(amount))
+
+--- Format elements ---
+Element: EXPR flags: 0x1 min: 12 max: 0 expr: scrub(amount)
+
+--- Formatted string ---
+"20 BOOK "
+>>>2
+=== 0
+format "%12(scrub(amount))"
+>>>1
+--- Context is first posting of the following transaction ---
+2004/05/27 Book Store
+ ; This note applies to all postings. :SecondTag:
+ Expenses:Books 20 BOOK @ $10
+ ; Metadata: Some Value
+ ; :ExampleTag:
+ ; Here follows a note describing the posting.
+ Liabilities:MasterCard $-200.00
+
+--- Input format string ---
+%12(scrub(amount))
+
+--- Format elements ---
+Element: EXPR flags: 0x0 min: 12 max: 0 expr: scrub(amount)
+
+--- Formatted string ---
+" 20 BOOK"
+>>>2
+=== 0
diff --git a/test/runtests.py b/test/runtests.py
new file mode 100755
index 00000000..9afbd25d
--- /dev/null
+++ b/test/runtests.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python
+
+import random
+import string
+import signal
+import os
+import sys
+
+true, false = 1, 0
+
+options = [
+ "--account=TempAccount",
+ "--actual",
+ "--add-budget",
+ "--amount-data",
+ "--amount=a",
+ "--ansi",
+ "--ansi-invert",
+ "--average",
+ #"--balance-format",
+ "--basis",
+ "--begin=2004/01",
+ "--budget",
+ "--by-payee",
+ #"--cache=/tmp/cache",
+ "--cleared",
+ "--collapse",
+ "--comm-as-payee",
+ #"--csv-register-format",
+ "--current",
+ "--date-format=%Y",
+ "--descend='$100'",
+ "--descend-if='t=={$100}'",
+ "--deviation",
+ "--display='a>10'",
+ "--dow",
+ "--download",
+ "--effective",
+ "--empty",
+ "--end=2005/01",
+ #"--equity-format",
+ #"--file=/tmp/file",
+ "--forecast='d<[2006]'",
+ "--format=%Y",
+ #"--full-help",
+ "--gain",
+ "--head=10",
+ #"--help",
+ #"--help-calc",
+ #"--help-comm",
+ #"--help-disp",
+ #"--init-file=/tmp/init",
+ #"--input-date-format",
+ "--limit='a>10'",
+ "--lots",
+ "--lot-prices",
+ "--lot-dates",
+ "--lot-tags",
+ "--market",
+ "--monthly",
+ "--no-cache",
+ #"--output=/tmp/output",
+ #"--pager",
+ #"--percentage",
+ "--performance",
+ "--period-sort=A\\(t\\)",
+ "--period=oct",
+ #"--plot-amount-format",
+ #"--plot-total-format",
+ "--price",
+ "--price-exp=1000",
+ #"--price-db=/tmp/foo",
+ #"--prices-format",
+ #"--print-format",
+ "--quantity",
+ "--real",
+ #"--reconcile",
+ #"--reconcile-date",
+ #"--register-format",
+ "--related",
+ "--sort=A\\(t\\)",
+ "--subtotal",
+ "--tail=5",
+ "--total-data",
+ "--total=O",
+ "--totals",
+ "--unbudgeted",
+ "--uncleared",
+ #"--version",
+ "--weekly",
+ "--wide",
+ "--yearly",
+]
+
+commands = [
+ "bal rent",
+ "bal ira",
+ "bal auto",
+ "reg rent",
+ "reg ira",
+ "reg expenses:food",
+ "print rent",
+ "print irc",
+ "xml rent",
+ "xml irc",
+ "equity rent",
+ "equity ira",
+ "prices AAPL",
+]
+
+random.seed ()
+
+loop = true
+count = 0
+errors = 0
+if len(sys.argv) > 1:
+ errors = int(sys.argv[1])
+signals = 0
+
+while loop:
+ try:
+ n = random.randint (0, len (options))
+ opts = random.sample (options, n)
+ for cmd in commands:
+ if os.path.exists ("/tmp/out"):
+ os.unlink ("/tmp/out")
+
+ cmd = "./ledger -f tools/standard.dat " + string.join(opts, " ") + " " + cmd + \
+ " >> /tmp/out 2>&1"
+
+ sys.stdout = open ("/tmp/out", "w")
+ print "::", cmd
+ sys.stdout.close ()
+
+ ret = os.system (cmd)
+
+ sys.stdout = open ("/tmp/out", "a")
+
+ # Convert an odd UNIX return type into the appropriate
+ # signal indication.
+ if ret and ret % 256 == 0 and ret / 256 > 127:
+ ret = 0x100 + (ret / 256 - 128)
+
+ if ret and ret % 256 == 0:
+ print "ERROR: Return value", ret / 256
+ sys.stdout.close ()
+ os.system ("cat /tmp/out >> errors.out")
+ errors += 1
+ elif ret:
+ if ret % 256 == signal.SIGINT:
+ loop = false
+ break
+ print "SIGNAL: Return value", ret % 256
+ sys.stdout.close ()
+ os.system ("cat /tmp/out >> signals.out")
+ signals += 1
+ else:
+ sys.stdout.close ()
+ os.system ("cat /tmp/out >> results.out")
+
+ sys.stdout = sys.__stdout__
+ count += 1
+ if count < 10 or \
+ (count < 100 and count % 10 == 0) or \
+ (count < 1000 and count % 100 == 0) or \
+ count % 1000 == 0:
+ if signals > 0 and errors > 0:
+ print "%d tests ... (%d signals, %d errors)" % \
+ (count, signals, errors)
+ elif signals > 0:
+ print "%d tests ... (%d signals)" % \
+ (count, signals)
+ elif errors > 0:
+ print "%d tests ... (%d errors)" % \
+ (count, errors)
+ else:
+ print "%d tests ..." % count
+
+ except KeyboardInterrupt:
+ loop = false
diff --git a/test/unit/t_amount.cc b/test/unit/t_amount.cc
new file mode 100644
index 00000000..2c91ee98
--- /dev/null
+++ b/test/unit/t_amount.cc
@@ -0,0 +1,1329 @@
+#include <system.hh>
+
+#include "t_amount.h"
+
+#include "amount.h"
+#include "commodity.h"
+
+using namespace ledger;
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(AmountTestCase, "math");
+
+void AmountTestCase::setUp()
+{
+ times_initialize();
+ amount_t::initialize();
+
+ // Cause the display precision for dollars to be initialized to 2.
+ amount_t x1("$1.00");
+ assertTrue(x1);
+
+ amount_t::stream_fullstrings = true; // make reports from UnitTests accurate
+}
+
+void AmountTestCase::tearDown()
+{
+ amount_t::stream_fullstrings = false;
+ amount_t::shutdown();
+ times_shutdown();
+}
+
+void AmountTestCase::testParser()
+{
+ amount_t x0;
+ amount_t x1;
+ amount_t x2;
+ amount_t x3;
+ amount_t x4("123.456");
+ amount_t x5(x4);
+ amount_t x6(x4);
+ amount_t x7(x4);
+ amount_t x8("$123.45");
+ amount_t x9(x8);
+ amount_t x10(x8);
+ amount_t x11(x8);
+ amount_t x12("$100");
+
+ assertEqual(amount_t::precision_t(2), x12.commodity().precision());
+
+#ifndef NOT_FOR_PYTHON
+ string buf("$100...");
+ std::istringstream input(buf);
+ amount_t x13;
+ x13.parse(input);
+ assertEqual(x12, x13);
+#endif // NOT_FOR_PYTHON
+
+ amount_t x14;
+ assertThrow(x14.parse("DM"), amount_error);
+
+ amount_t x15("$1.000.000,00"); // parsing this switches us to European
+
+ amount_t x16("$2000");
+ assertEqual(string("$2.000,00"), x16.to_string());
+ x16.parse("$2000,00");
+ assertEqual(string("$2.000,00"), x16.to_string());
+
+ // Since European-ness is an additive quality, we must switch back
+ // to American-ness manually
+ x15.commodity().drop_flags(COMMODITY_STYLE_EUROPEAN);
+
+ amount_t x17("$1,000,000.00"); // parsing this switches back to American
+
+ amount_t x18("$2000");
+ assertEqual(string("$2,000.00"), x18.to_string());
+ x18.parse("$2,000");
+ assertEqual(string("$2,000.00"), x18.to_string());
+
+ assertEqual(x15, x17);
+
+ amount_t x19("EUR 1000");
+ amount_t x20("EUR 1000");
+
+ assertEqual(string("EUR 1000"), x19.to_string());
+ assertEqual(string("EUR 1000"), x20.to_string());
+
+ x1.parse("$100.0000", PARSE_NO_MIGRATE);
+ assertEqual(amount_t::precision_t(2), x12.commodity().precision());
+ assertEqual(x1.commodity(), x12.commodity());
+ assertEqual(x1, x12);
+
+ x0.parse("$100.0000");
+ assertEqual(amount_t::precision_t(4), x12.commodity().precision());
+ assertEqual(x0.commodity(), x12.commodity());
+ assertEqual(x0, x12);
+
+ x2.parse("$100.00", PARSE_NO_REDUCE);
+ assertEqual(x2, x12);
+ x3.parse("$100.00", PARSE_NO_MIGRATE | PARSE_NO_REDUCE);
+ assertEqual(x3, x12);
+
+ x4.parse("$100.00");
+ assertEqual(x4, x12);
+ x5.parse("$100.00", PARSE_NO_MIGRATE);
+ assertEqual(x5, x12);
+ x6.parse("$100.00", PARSE_NO_REDUCE);
+ assertEqual(x6, x12);
+ x7.parse("$100.00", PARSE_NO_MIGRATE | PARSE_NO_REDUCE);
+ assertEqual(x7, x12);
+
+ x8.parse("$100.00");
+ assertEqual(x8, x12);
+ x9.parse("$100.00", PARSE_NO_MIGRATE);
+ assertEqual(x9, x12);
+ x10.parse("$100.00", PARSE_NO_REDUCE);
+ assertEqual(x10, x12);
+ x11.parse("$100.00", PARSE_NO_MIGRATE | PARSE_NO_REDUCE);
+ assertEqual(x11, x12);
+
+ assertValid(x0);
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x5);
+ assertValid(x6);
+ assertValid(x7);
+ assertValid(x8);
+ assertValid(x9);
+ assertValid(x10);
+ assertValid(x11);
+ assertValid(x12);
+}
+
+void AmountTestCase::testConstructors()
+{
+ amount_t x0;
+ amount_t x1(123456L);
+ amount_t x2(123456UL);
+ amount_t x3("123.456");
+ amount_t x5("123456");
+ amount_t x6("123.456");
+ amount_t x7(string("123456"));
+ amount_t x8(string("123.456"));
+ amount_t x9(x3);
+ amount_t x10(x6);
+ amount_t x11(x8);
+
+ assertEqual(amount_t(), x0);
+ assertNotEqual(amount_t("0"), x0);
+ assertNotEqual(amount_t("0.0"), x0);
+ assertEqual(x2, x1);
+ assertEqual(x5, x1);
+ assertEqual(x7, x1);
+ assertEqual(x6, x3);
+ assertEqual(x8, x3);
+ assertEqual(x10, x3);
+ assertEqual(x10, x9);
+
+ assertValid(x0);
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x5);
+ assertValid(x6);
+ assertValid(x7);
+ assertValid(x8);
+ assertValid(x9);
+ assertValid(x10);
+ assertValid(x11);
+}
+
+void AmountTestCase::testCommodityConstructors()
+{
+ amount_t x1("$123.45");
+ amount_t x2("-$123.45");
+ amount_t x3("$-123.45");
+ amount_t x4("DM 123.45");
+ amount_t x5("-DM 123.45");
+ amount_t x6("DM -123.45");
+ amount_t x7("123.45 euro");
+ amount_t x8("-123.45 euro");
+ amount_t x9("123.45€");
+ amount_t x10("-123.45€");
+
+ assertEqual(amount_t("$123.45"), x1);
+ assertEqual(amount_t("-$123.45"), x2);
+ assertEqual(amount_t("$-123.45"), x3);
+ assertEqual(amount_t("DM 123.45"), x4);
+ assertEqual(amount_t("-DM 123.45"), x5);
+ assertEqual(amount_t("DM -123.45"), x6);
+ assertEqual(amount_t("123.45 euro"), x7);
+ assertEqual(amount_t("-123.45 euro"), x8);
+ assertEqual(amount_t("123.45€"), x9);
+ assertEqual(amount_t("-123.45€"), x10);
+
+ assertEqual(string("$123.45"), x1.to_string());
+ assertEqual(string("$-123.45"), x2.to_string());
+ assertEqual(string("$-123.45"), x3.to_string());
+ assertEqual(string("DM 123.45"), x4.to_string());
+ assertEqual(string("DM -123.45"), x5.to_string());
+ assertEqual(string("DM -123.45"), x6.to_string());
+ assertEqual(string("123.45 euro"), x7.to_string());
+ assertEqual(string("-123.45 euro"), x8.to_string());
+ assertEqual(string("123.45€"), x9.to_string());
+ assertEqual(string("-123.45€"), x10.to_string());
+
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+ assertValid(x5);
+ assertValid(x6);
+ assertValid(x7);
+ assertValid(x8);
+ assertValid(x9);
+ assertValid(x10);
+}
+
+#ifndef NOT_FOR_PYTHON
+
+void AmountTestCase::testAssignment()
+{
+ amount_t x0;
+ amount_t x1;
+ amount_t x2;
+ amount_t x3;
+ amount_t x5;
+ amount_t x6;
+ amount_t x7;
+ amount_t x8;
+ amount_t x9;
+ amount_t x10;
+
+ x1 = 123456L;
+ x2 = 123456UL;
+ x3 = "123.456";
+ x5 = "123456";
+ x6 = "123.456";
+ x7 = string("123456");
+ x8 = string("123.456");
+ x9 = x3;
+ x10 = amount_t(x6);
+
+ assertEqual(x2, x1);
+ assertEqual(x5, x1);
+ assertEqual(x7, x1);
+ assertEqual(x6, x3);
+ assertEqual(x8, x3);
+ assertEqual(x10, x3);
+ assertEqual(x10, x9);
+
+ assertFalse(x1.is_null());
+ x1 = x0; // sets x1 back to uninitialized state
+ assertTrue(x0.is_null());
+ assertTrue(x1.is_null());
+
+ assertValid(x0);
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x5);
+ assertValid(x6);
+ assertValid(x7);
+ assertValid(x8);
+ assertValid(x9);
+ assertValid(x10);
+}
+
+void AmountTestCase::testCommodityAssignment()
+{
+ amount_t x1;
+ amount_t x2;
+ amount_t x3;
+ amount_t x4;
+ amount_t x5;
+ amount_t x6;
+ amount_t x7;
+ amount_t x8;
+ amount_t x9;
+ amount_t x10;
+
+ x1 = "$123.45";
+ x2 = "-$123.45";
+ x3 = "$-123.45";
+ x4 = "DM 123.45";
+ x5 = "-DM 123.45";
+ x6 = "DM -123.45";
+ x7 = "123.45 euro";
+ x8 = "-123.45 euro";
+ x9 = "123.45€";
+ x10 = "-123.45€";
+
+ assertEqual(amount_t("$123.45"), x1);
+ assertEqual(amount_t("-$123.45"), x2);
+ assertEqual(amount_t("$-123.45"), x3);
+ assertEqual(amount_t("DM 123.45"), x4);
+ assertEqual(amount_t("-DM 123.45"), x5);
+ assertEqual(amount_t("DM -123.45"), x6);
+ assertEqual(amount_t("123.45 euro"), x7);
+ assertEqual(amount_t("-123.45 euro"), x8);
+ assertEqual(amount_t("123.45€"), x9);
+ assertEqual(amount_t("-123.45€"), x10);
+
+ assertEqual(string("$123.45"), x1.to_string());
+ assertEqual(string("$-123.45"), x2.to_string());
+ assertEqual(string("$-123.45"), x3.to_string());
+ assertEqual(string("DM 123.45"), x4.to_string());
+ assertEqual(string("DM -123.45"), x5.to_string());
+ assertEqual(string("DM -123.45"), x6.to_string());
+ assertEqual(string("123.45 euro"), x7.to_string());
+ assertEqual(string("-123.45 euro"), x8.to_string());
+ assertEqual(string("123.45€"), x9.to_string());
+ assertEqual(string("-123.45€"), x10.to_string());
+
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+ assertValid(x5);
+ assertValid(x6);
+ assertValid(x7);
+ assertValid(x8);
+ assertValid(x9);
+ assertValid(x10);
+}
+
+#endif // NOT_FOR_PYTHON
+
+void AmountTestCase::testEquality()
+{
+ amount_t x1(123456L);
+ amount_t x2(456789L);
+ amount_t x3(333333L);
+ amount_t x4("123456.0");
+ amount_t x5("123456.0");
+ amount_t x6("123456.0");
+
+ assertTrue(x1 == 123456L);
+ assertTrue(x1 != x2);
+ assertTrue(x1 == (x2 - x3));
+ assertTrue(x1 == x4);
+ assertTrue(x4 == x5);
+ assertTrue(x4 == x6);
+
+ assertTrue(x1 == 123456L);
+ assertTrue(123456L == x1);
+ assertTrue(x1 == 123456UL);
+ assertTrue(123456UL == x1);
+ assertTrue(x1 == amount_t("123456.0"));
+ assertTrue(amount_t("123456.0") == x1);
+
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+ assertValid(x5);
+ assertValid(x6);
+}
+
+void AmountTestCase::testCommodityEquality()
+{
+ amount_t x0;
+ amount_t x1("$123.45");
+ amount_t x2("-$123.45");
+ amount_t x3("$-123.45");
+ amount_t x4("DM 123.45");
+ amount_t x5("-DM 123.45");
+ amount_t x6("DM -123.45");
+ amount_t x7("123.45 euro");
+ amount_t x8("-123.45 euro");
+ amount_t x9("123.45€");
+ amount_t x10("-123.45€");
+
+ assertTrue(x0.is_null());
+ assertThrow(x0.is_zero(), amount_error);
+ assertThrow(x0.is_realzero(), amount_error);
+ assertThrow(x0.sign(), amount_error);
+ assertThrow(x0.compare(x1), amount_error);
+ assertThrow(x0.compare(x2), amount_error);
+ assertThrow(x0.compare(x0), amount_error);
+
+ assertTrue(x1 != x2);
+ assertTrue(x1 != x4);
+ assertTrue(x1 != x7);
+ assertTrue(x1 != x9);
+ assertTrue(x2 == x3);
+ assertTrue(x4 != x5);
+ assertTrue(x5 == x6);
+ assertTrue(x7 == - x8);
+ assertTrue(x9 == - x10);
+
+ assertValid(x0);
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+ assertValid(x5);
+ assertValid(x6);
+ assertValid(x7);
+ assertValid(x8);
+ assertValid(x9);
+ assertValid(x10);
+}
+
+void AmountTestCase::testComparisons()
+{
+ amount_t x0;
+ amount_t x1(-123L);
+ amount_t x2(123L);
+ amount_t x3("-123.45");
+ amount_t x4("123.45");
+ amount_t x5("-123.45");
+ amount_t x6("123.45");
+
+ assertThrow(x0 > x1, amount_error);
+ assertThrow(x0 < x2, amount_error);
+ assertThrow(x0 > x3, amount_error);
+ assertThrow(x0 < x4, amount_error);
+ assertThrow(x0 > x5, amount_error);
+ assertThrow(x0 < x6, amount_error);
+
+ assertTrue(x1 > x3);
+ assertTrue(x3 <= x5);
+ assertTrue(x3 >= x5);
+ assertTrue(x3 < x1);
+ assertTrue(x3 < x4);
+
+ assertTrue(x1 < 100L);
+ assertTrue(100L > x1);
+ assertTrue(x1 < 100UL);
+ assertTrue(100UL > x1);
+#ifndef NOT_FOR_PYTHON
+ assertTrue(x1 < 100.0);
+ assertTrue(100.0 > x1);
+#endif // NOT_FOR_PYTHON
+
+ assertValid(x0);
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+ assertValid(x5);
+ assertValid(x6);
+}
+
+void AmountTestCase::testCommodityComparisons()
+{
+ amount_t x1("$-123");
+ amount_t x2("$123.00");
+ amount_t x3(internalAmount("$-123.4544"));
+ amount_t x4(internalAmount("$123.4544"));
+ amount_t x5("$-123.45");
+ amount_t x6("$123.45");
+ amount_t x7("DM 123.45");
+
+ assertTrue(x1 > x3);
+ assertTrue(x3 <= x5);
+ assertTrue(x3 < x5);
+ assertTrue(x3 <= x5);
+ assertFalse(x3 == x5);
+ assertTrue(x3 < x1);
+ assertTrue(x3 < x4);
+ assertFalse(x6 == x7);
+ assertThrow(x6 < x7, amount_error);
+
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+ assertValid(x5);
+ assertValid(x6);
+}
+
+void AmountTestCase::testIntegerAddition()
+{
+ amount_t x0;
+ amount_t x1(123L);
+ amount_t y1(456L);
+
+ assertEqual(amount_t(579L), x1 + y1);
+ assertEqual(amount_t(579L), x1 + 456L);
+ assertEqual(amount_t(579L), 456L + x1);
+
+ x1 += amount_t(456L);
+ assertEqual(amount_t(579L), x1);
+ x1 += 456L;
+ assertEqual(amount_t(1035L), x1);
+
+ amount_t x4("123456789123456789123456789");
+
+ assertEqual(amount_t("246913578246913578246913578"), x4 + x4);
+
+ assertValid(x0);
+ assertValid(x1);
+ assertValid(y1);
+ assertValid(x4);
+}
+
+void AmountTestCase::testFractionalAddition()
+{
+ amount_t x1("123.123");
+ amount_t y1("456.456");
+
+ assertEqual(amount_t("579.579"), x1 + y1);
+ assertEqual(amount_t("579.579"), x1 + amount_t("456.456"));
+ assertEqual(amount_t("579.579"), amount_t("456.456") + x1);
+
+ x1 += amount_t("456.456");
+ assertEqual(amount_t("579.579"), x1);
+ x1 += amount_t("456.456");
+ assertEqual(amount_t("1036.035"), x1);
+ x1 += 456L;
+ assertEqual(amount_t("1492.035"), x1);
+
+ amount_t x2("123456789123456789.123456789123456789");
+
+ assertEqual(amount_t("246913578246913578.246913578246913578"), x2 + x2);
+
+ assertValid(x1);
+ assertValid(y1);
+ assertValid(x2);
+}
+
+void AmountTestCase::testCommodityAddition()
+{
+ amount_t x0;
+ amount_t x1("$123.45");
+ amount_t x2(internalAmount("$123.456789"));
+ amount_t x3("DM 123.45");
+ amount_t x4("123.45 euro");
+ amount_t x5("123.45€");
+ amount_t x6("123.45");
+
+ assertEqual(amount_t("$246.90"), x1 + x1);
+ assertNotEqual(amount_t("$246.91"), x1 + x2);
+ assertEqual(internalAmount("$246.906789"), x1 + x2);
+
+ // Converting to string drops internal precision
+ assertEqual(string("$246.90"), (x1 + x1).to_string());
+ assertEqual(string("$246.91"), (x1 + x2).to_string());
+
+ assertThrow(x1 + x0, amount_error);
+ assertThrow(x0 + x1, amount_error);
+ assertThrow(x0 + x0, amount_error);
+ assertThrow(x1 + x3, amount_error);
+ assertThrow(x1 + x4, amount_error);
+ assertThrow(x1 + x5, amount_error);
+ assertEqual(string("$246.90"), (x1 + x6).to_string());
+#ifndef NOT_FOR_PYTHON
+ assertEqual(string("$246.90"), (x1 + 123.45).to_string());
+#endif // NOT_FOR_PYTHON
+ assertEqual(string("$246.45"), (x1 + 123L).to_string());
+
+ assertEqual(amount_t("DM 246.90"), x3 + x3);
+ assertEqual(amount_t("246.90 euro"), x4 + x4);
+ assertEqual(amount_t("246.90€"), x5 + x5);
+
+ assertEqual(string("DM 246.90"), (x3 + x3).to_string());
+ assertEqual(string("246.90 euro"), (x4 + x4).to_string());
+ assertEqual(string("246.90€"), (x5 + x5).to_string());
+
+ x1 += amount_t("$456.45");
+ assertEqual(amount_t("$579.90"), x1);
+ x1 += amount_t("$456.45");
+ assertEqual(amount_t("$1036.35"), x1);
+ x1 += amount_t("$456");
+ assertEqual(amount_t("$1492.35"), x1);
+
+ amount_t x7(internalAmount("$123456789123456789.123456789123456789"));
+
+ assertEqual(internalAmount("$246913578246913578.246913578246913578"), x7 + x7);
+
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+ assertValid(x5);
+ assertValid(x6);
+ assertValid(x7);
+}
+
+void AmountTestCase::testIntegerSubtraction()
+{
+ amount_t x1(123L);
+ amount_t y1(456L);
+
+ assertEqual(amount_t(333L), y1 - x1);
+ assertEqual(amount_t(-333L), x1 - y1);
+ assertEqual(amount_t(23L), x1 - 100L);
+ assertEqual(amount_t(-23L), 100L - x1);
+
+ x1 -= amount_t(456L);
+ assertEqual(amount_t(-333L), x1);
+ x1 -= 456L;
+ assertEqual(amount_t(-789L), x1);
+
+ amount_t x4("123456789123456789123456789");
+ amount_t y4("8238725986235986");
+
+ assertEqual(amount_t("123456789115218063137220803"), x4 - y4);
+ assertEqual(amount_t("-123456789115218063137220803"), y4 - x4);
+
+ assertValid(x1);
+ assertValid(y1);
+ assertValid(x4);
+ assertValid(y4);
+}
+
+void AmountTestCase::testFractionalSubtraction()
+{
+ amount_t x1("123.123");
+ amount_t y1("456.456");
+
+ assertEqual(amount_t("-333.333"), x1 - y1);
+ assertEqual(amount_t("333.333"), y1 - x1);
+
+ x1 -= amount_t("456.456");
+ assertEqual(amount_t("-333.333"), x1);
+ x1 -= amount_t("456.456");
+ assertEqual(amount_t("-789.789"), x1);
+ x1 -= 456L;
+ assertEqual(amount_t("-1245.789"), x1);
+
+ amount_t x2("123456789123456789.123456789123456789");
+ amount_t y2("9872345982459.248974239578");
+
+ assertEqual(amount_t("123446916777474329.874482549545456789"), x2 - y2);
+ assertEqual(amount_t("-123446916777474329.874482549545456789"), y2 - x2);
+
+ assertValid(x1);
+ assertValid(y1);
+ assertValid(x2);
+ assertValid(y2);
+}
+
+void AmountTestCase::testCommoditySubtraction()
+{
+ amount_t x0;
+ amount_t x1("$123.45");
+ amount_t x2(internalAmount("$123.456789"));
+ amount_t x3("DM 123.45");
+ amount_t x4("123.45 euro");
+ amount_t x5("123.45€");
+ amount_t x6("123.45");
+
+ assertNotEqual(amount_t(), x1 - x1);
+ assertEqual(amount_t("$0"), x1 - x1);
+ assertEqual(amount_t("$23.45"), x1 - amount_t("$100.00"));
+ assertEqual(amount_t("$-23.45"), amount_t("$100.00") - x1);
+ assertNotEqual(amount_t("$-0.01"), x1 - x2);
+ assertEqual(internalAmount("$-0.006789"), x1 - x2);
+
+ // Converting to string drops internal precision. If an amount is
+ // zero, it drops the commodity as well.
+ assertEqual(string("$0.00"), (x1 - x1).to_string());
+ assertEqual(string("$-0.01"), (x1 - x2).to_string());
+
+ assertThrow(x1 - x0, amount_error);
+ assertThrow(x0 - x1, amount_error);
+ assertThrow(x0 - x0, amount_error);
+ assertThrow(x1 - x3, amount_error);
+ assertThrow(x1 - x4, amount_error);
+ assertThrow(x1 - x5, amount_error);
+ assertEqual(string("$0.00"), (x1 - x6).to_string());
+#ifndef NOT_FOR_PYTHON
+ assertEqual(string("$-0.00"), (x1 - 123.45).to_string());
+#endif // NOT_FOR_PYTHON
+ assertEqual(string("$0.45"), (x1 - 123L).to_string());
+
+ assertEqual(amount_t("DM 0.00"), x3 - x3);
+ assertEqual(amount_t("DM 23.45"), x3 - amount_t("DM 100.00"));
+ assertEqual(amount_t("DM -23.45"), amount_t("DM 100.00") - x3);
+ assertEqual(amount_t("0.00 euro"), x4 - x4);
+ assertEqual(amount_t("23.45 euro"), x4 - amount_t("100.00 euro"));
+ assertEqual(amount_t("-23.45 euro"), amount_t("100.00 euro") - x4);
+ assertEqual(amount_t("0.00€"), x5 - x5);
+ assertEqual(amount_t("23.45€"), x5 - amount_t("100.00€"));
+ assertEqual(amount_t("-23.45€"), amount_t("100.00€") - x5);
+
+ assertEqual(string("DM 0.00"), (x3 - x3).to_string());
+ assertEqual(string("DM 23.45"), (x3 - amount_t("DM 100.00")).to_string());
+ assertEqual(string("DM -23.45"), (amount_t("DM 100.00") - x3).to_string());
+ assertEqual(string("0.00 euro"), (x4 - x4).to_string());
+ assertEqual(string("23.45 euro"), (x4 - amount_t("100.00 euro")).to_string());
+ assertEqual(string("-23.45 euro"), (amount_t("100.00 euro") - x4).to_string());
+ assertEqual(string("0.00€"), (x5 - x5).to_string());
+ assertEqual(string("23.45€"), (x5 - amount_t("100.00€")).to_string());
+ assertEqual(string("-23.45€"), (amount_t("100.00€") - x5).to_string());
+
+ x1 -= amount_t("$456.45");
+ assertEqual(amount_t("$-333.00"), x1);
+ x1 -= amount_t("$456.45");
+ assertEqual(amount_t("$-789.45"), x1);
+ x1 -= amount_t("$456");
+ assertEqual(amount_t("$-1245.45"), x1);
+
+ amount_t x7(internalAmount("$123456789123456789.123456789123456789"));
+ amount_t x8(internalAmount("$2354974984698.98459845984598"));
+
+ assertEqual(internalAmount("$123454434148472090.138858329277476789"), x7 - x8);
+ assertEqual(string("$123454434148472090.138858329277476789"), (x7 - x8).to_string());
+ assertEqual(string("$123454434148472090.14"),
+ (amount_t("$1.00") * (x7 - x8)).to_string());
+ assertEqual(internalAmount("$-123454434148472090.138858329277476789"), x8 - x7);
+ assertEqual(string("$-123454434148472090.138858329277476789"), (x8 - x7).to_string());
+ assertEqual(string("$-123454434148472090.14"),
+ (amount_t("$1.00") * (x8 - x7)).to_string());
+
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+ assertValid(x5);
+ assertValid(x6);
+ assertValid(x7);
+ assertValid(x8);
+}
+
+void AmountTestCase::testIntegerMultiplication()
+{
+ amount_t x1(123L);
+ amount_t y1(456L);
+
+ assertEqual(amount_t(0L), x1 * 0L);
+ assertEqual(amount_t(0L), amount_t(0L) * x1);
+ assertEqual(amount_t(0L), 0L * x1);
+ assertEqual(x1, x1 * 1L);
+ assertEqual(x1, amount_t(1L) * x1);
+ assertEqual(x1, 1L * x1);
+ assertEqual(- x1, x1 * -1L);
+ assertEqual(- x1, amount_t(-1L) * x1);
+ assertEqual(- x1, -1L * x1);
+ assertEqual(amount_t(56088L), x1 * y1);
+ assertEqual(amount_t(56088L), y1 * x1);
+ assertEqual(amount_t(56088L), x1 * 456L);
+ assertEqual(amount_t(56088L), amount_t(456L) * x1);
+ assertEqual(amount_t(56088L), 456L * x1);
+
+ x1 *= amount_t(123L);
+ assertEqual(amount_t(15129L), x1);
+ x1 *= 123L;
+ assertEqual(amount_t(1860867L), x1);
+
+ amount_t x4("123456789123456789123456789");
+
+ assertEqual(amount_t("15241578780673678546105778281054720515622620750190521"),
+ x4 * x4);
+
+ assertValid(x1);
+ assertValid(y1);
+ assertValid(x4);
+}
+
+void AmountTestCase::testFractionalMultiplication()
+{
+ amount_t x1("123.123");
+ amount_t y1("456.456");
+
+ assertEqual(amount_t(0L), x1 * 0L);
+ assertEqual(amount_t(0L), amount_t(0L) * x1);
+ assertEqual(amount_t(0L), 0L * x1);
+ assertEqual(x1, x1 * 1L);
+ assertEqual(x1, amount_t(1L) * x1);
+ assertEqual(x1, 1L * x1);
+ assertEqual(- x1, x1 * -1L);
+ assertEqual(- x1, amount_t(-1L) * x1);
+ assertEqual(- x1, -1L * x1);
+ assertEqual(amount_t("56200.232088"), x1 * y1);
+ assertEqual(amount_t("56200.232088"), y1 * x1);
+ assertEqual(amount_t("56200.232088"), x1 * amount_t("456.456"));
+ assertEqual(amount_t("56200.232088"), amount_t("456.456") * x1);
+ assertEqual(amount_t("56200.232088"), amount_t("456.456") * x1);
+
+ x1 *= amount_t("123.123");
+ assertEqual(amount_t("15159.273129"), x1);
+ x1 *= amount_t("123.123");
+ assertEqual(amount_t("1866455.185461867"), x1);
+ x1 *= 123L;
+ assertEqual(amount_t("229573987.811809641"), x1);
+
+ amount_t x2("123456789123456789.123456789123456789");
+
+ assertEqual(amount_t("15241578780673678546105778311537878.046486820281054720515622620750190521"),
+ x2 * x2);
+
+ assertValid(x1);
+ assertValid(y1);
+ assertValid(x2);
+}
+
+void AmountTestCase::testCommodityMultiplication()
+{
+ amount_t x0;
+ amount_t x1("$123.12");
+ amount_t y1("$456.45");
+ amount_t x2(internalAmount("$123.456789"));
+ amount_t x3("DM 123.45");
+ amount_t x4("123.45 euro");
+ amount_t x5("123.45€");
+
+ assertEqual(amount_t("$0.00"), x1 * 0L);
+ assertEqual(amount_t("$0.00"), 0L * x1);
+ assertEqual(x1, x1 * 1L);
+ assertEqual(x1, 1L * x1);
+ assertEqual(- x1, x1 * -1L);
+ assertEqual(- x1, -1L * x1);
+ assertEqual(internalAmount("$56198.124"), x1 * y1);
+ assertEqual(string("$56198.12"), (x1 * y1).to_string());
+ assertEqual(internalAmount("$56198.124"), y1 * x1);
+ assertEqual(string("$56198.12"), (y1 * x1).to_string());
+
+ // Internal amounts retain their precision, even when being
+ // converted to strings
+ assertEqual(internalAmount("$15199.99986168"), x1 * x2);
+ assertEqual(internalAmount("$15199.99986168"), x2 * x1);
+ assertEqual(string("$15200.00"), (x1 * x2).to_string());
+ assertEqual(string("$15199.99986168"), (x2 * x1).to_string());
+
+ assertThrow(x1 * x0, amount_error);
+ assertThrow(x0 * x1, amount_error);
+ assertThrow(x0 * x0, amount_error);
+ //assertThrow(x1 * x3, amount_error);
+ //assertThrow(x1 * x4, amount_error);
+ //assertThrow(x1 * x5, amount_error);
+
+ x1 *= amount_t("123.12");
+ assertEqual(internalAmount("$15158.5344"), x1);
+ assertEqual(string("$15158.53"), x1.to_string());
+ x1 *= amount_t("123.12");
+ assertEqual(internalAmount("$1866318.755328"), x1);
+ assertEqual(string("$1866318.76"), x1.to_string());
+ x1 *= 123L;
+ assertEqual(internalAmount("$229557206.905344"), x1);
+ assertEqual(string("$229557206.91"), x1.to_string());
+
+ amount_t x7(internalAmount("$123456789123456789.123456789123456789"));
+
+ assertEqual(internalAmount("$15241578780673678546105778311537878.046486820281054720515622620750190521"),
+ x7 * x7);
+
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+ assertValid(x5);
+ assertValid(x7);
+}
+
+void AmountTestCase::testIntegerDivision()
+{
+ amount_t x1(123L);
+ amount_t y1(456L);
+
+ assertThrow(x1 / 0L, amount_error);
+ assertEqual(amount_t(0L), amount_t(0L) / x1);
+ assertEqual(amount_t(0L), 0L / x1);
+ assertEqual(x1, x1 / 1L);
+ assertEqual(string("0.00813"), (amount_t(1L) / x1).to_string());
+ assertEqual(string("0.00813"), (1L / x1).to_string());
+ assertEqual(- x1, x1 / -1L);
+ assertEqual(string("-0.00813"), (amount_t(-1L) / x1).to_string());
+ assertEqual(string("-0.00813"), (-1L / x1).to_string());
+ assertEqual(string("0.269737"), (x1 / y1).to_string());
+ assertEqual(string("3.707317"), (y1 / x1).to_string());
+ assertEqual(string("0.269737"), (x1 / 456L).to_string());
+ assertEqual(string("3.707317"), (amount_t(456L) / x1).to_string());
+ assertEqual(string("3.707317"), (456L / x1).to_string());
+
+ x1 /= amount_t(456L);
+ assertEqual(string("0.269737"), x1.to_string());
+ x1 /= 456L;
+ assertEqual(string("0.000591528163"), x1.to_string());
+
+ amount_t x4("123456789123456789123456789");
+ amount_t y4("56");
+
+ assertEqual(amount_t(1L), x4 / x4);
+ assertEqual(string("2204585520061728377204585.517857"), (x4 / y4).to_string());
+
+ assertEqual(amount_t("0.000000000000000000000000000001"),
+ amount_t("10") / amount_t("10000000000000000000000000000000"));
+
+ assertValid(x1);
+ assertValid(y1);
+ assertValid(x4);
+ assertValid(y4);
+}
+
+void AmountTestCase::testFractionalDivision()
+{
+ amount_t x1("123.123");
+ amount_t y1("456.456");
+
+ assertThrow(x1 / 0L, amount_error);
+ assertEqual(string("0.0081219593"), (amount_t("1.0") / x1).to_string());
+ assertEqual(string("0.0081219593"), (amount_t("1.0") / x1).to_string());
+ assertEqual(x1, x1 / amount_t("1.0"));
+ assertEqual(string("0.0081219593"), (amount_t("1.0") / x1).to_string());
+ assertEqual(string("0.0081219593"), (amount_t("1.0") / x1).to_string());
+ assertEqual(- x1, x1 / amount_t("-1.0"));
+ assertEqual(string("-0.0081219593"), (amount_t("-1.0") / x1).to_string());
+ assertEqual(string("-0.0081219593"), (amount_t("-1.0") / x1).to_string());
+ assertEqual(string("0.269736842105"), (x1 / y1).to_string());
+ assertEqual(string("3.707317073171"), (y1 / x1).to_string());
+ assertEqual(string("0.269736842105"), (x1 / amount_t("456.456")).to_string());
+ assertEqual(string("3.707317073171"), (amount_t("456.456") / x1).to_string());
+ assertEqual(string("3.707317073171"), (amount_t("456.456") / x1).to_string());
+
+ x1 /= amount_t("456.456");
+ assertEqual(string("0.269736842105"), x1.to_string());
+ x1 /= amount_t("456.456");
+ assertEqual(string("0.000590937225286255757"), x1.to_string());
+ x1 /= 456L;
+ assertEqual(string("0.000001295914967733017011337"), x1.to_string());
+
+ amount_t x4("1234567891234567.89123456789");
+ amount_t y4("56.789");
+
+ assertEqual(amount_t("1.0"), x4 / x4);
+ assertEqual(string("21739560323910.75544972737484371973"), (x4 / y4).to_string());
+
+ assertValid(x1);
+ assertValid(y1);
+ assertValid(x4);
+ assertValid(y4);
+}
+
+void AmountTestCase::testCommodityDivision()
+{
+ amount_t x0;
+ amount_t x1("$123.12");
+ amount_t y1("$456.45");
+ amount_t x2(internalAmount("$123.456789"));
+ amount_t x3("DM 123.45");
+ amount_t x4("123.45 euro");
+ amount_t x5("123.45€");
+
+ assertThrow(x1 / 0L, amount_error);
+ assertEqual(amount_t("$0.00"), 0L / x1);
+ assertEqual(x1, x1 / 1L);
+ assertEqual(string("$0.00812216"), (1L / x1).to_fullstring());
+ assertEqual(- x1, x1 / -1L);
+ assertEqual(string("$-0.00812216"), (-1L / x1).to_fullstring());
+ assertEqual(string("$0.26973382"), (x1 / y1).to_fullstring());
+ assertEqual(string("$0.27"), (x1 / y1).to_string());
+ assertEqual(string("$3.70735867"), (y1 / x1).to_fullstring());
+ assertEqual(string("$3.71"), (y1 / x1).to_string());
+
+ // Internal amounts retain their precision, even when being
+ // converted to strings
+ assertEqual(string("$0.99727201"), (x1 / x2).to_fullstring());
+ assertEqual(string("$1.00273545321637"), (x2 / x1).to_fullstring());
+ assertEqual(string("$1.00"), (x1 / x2).to_string());
+ assertEqual(string("$1.00273545321637"), (x2 / x1).to_string());
+
+ assertThrow(x1 / x0, amount_error);
+ assertThrow(x0 / x1, amount_error);
+ assertThrow(x0 / x0, amount_error);
+ //assertThrow(x1 / x3, amount_error);
+ //assertThrow(x1 / x4, amount_error);
+ //assertThrow(x1 / x5, amount_error);
+
+ x1 /= amount_t("123.12");
+ assertEqual(string("$1.00"), x1.to_string());
+ x1 /= amount_t("123.12");
+ assertEqual(string("$0.00812216"), x1.to_fullstring());
+ assertEqual(string("$0.01"), x1.to_string());
+ x1 /= 123L;
+ assertEqual(string("$0.00006603"), x1.to_fullstring());
+ assertEqual(string("$0.00"), x1.to_string());
+
+ amount_t x6(internalAmount("$237235987235987.98723987235978"));
+ amount_t x7(internalAmount("$123456789123456789.123456789123456789"));
+
+ assertEqual(amount_t("$1"), x7 / x7);
+ assertEqual(string("$0.0019216115121765559608381226612019501"),
+ (x6 / x7).to_fullstring());
+ assertEqual(string("$520.39654928343335571379527154924040947272"),
+ (x7 / x6).to_fullstring());
+
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+ assertValid(x5);
+ assertValid(x6);
+ assertValid(x7);
+}
+
+void AmountTestCase::testNegation()
+{
+ amount_t x0;
+ amount_t x1(-123456L);
+ amount_t x3("-123.456");
+ amount_t x5("-123456");
+ amount_t x6("-123.456");
+ amount_t x7(string("-123456"));
+ amount_t x8(string("-123.456"));
+ amount_t x9(- x3);
+
+ assertThrow(x0.negated(), amount_error);
+ assertEqual(x5, x1);
+ assertEqual(x7, x1);
+ assertEqual(x6, x3);
+ assertEqual(x8, x3);
+ assertEqual(- x6, x9);
+ assertEqual(x3.negated(), x9);
+
+ amount_t x10(x9.negated());
+
+ assertEqual(x3, x10);
+
+ assertValid(x1);
+ assertValid(x3);
+ assertValid(x5);
+ assertValid(x6);
+ assertValid(x7);
+ assertValid(x8);
+ assertValid(x9);
+ assertValid(x10);
+}
+
+void AmountTestCase::testCommodityNegation()
+{
+ amount_t x1("$123.45");
+ amount_t x2("-$123.45");
+ amount_t x3("$-123.45");
+ amount_t x4("DM 123.45");
+ amount_t x5("-DM 123.45");
+ amount_t x6("DM -123.45");
+ amount_t x7("123.45 euro");
+ amount_t x8("-123.45 euro");
+ amount_t x9("123.45€");
+ amount_t x10("-123.45€");
+
+ assertEqual(amount_t("$-123.45"), - x1);
+ assertEqual(amount_t("$123.45"), - x2);
+ assertEqual(amount_t("$123.45"), - x3);
+ assertEqual(amount_t("DM -123.45"), - x4);
+ assertEqual(amount_t("DM 123.45"), - x5);
+ assertEqual(amount_t("DM 123.45"), - x6);
+ assertEqual(amount_t("-123.45 euro"), - x7);
+ assertEqual(amount_t("123.45 euro"), - x8);
+ assertEqual(amount_t("-123.45€"), - x9);
+ assertEqual(amount_t("123.45€"), - x10);
+
+ assertEqual(amount_t("$-123.45"), x1.negated());
+ assertEqual(amount_t("$123.45"), x2.negated());
+ assertEqual(amount_t("$123.45"), x3.negated());
+
+ assertEqual(string("$-123.45"), (- x1).to_string());
+ assertEqual(string("$123.45"), (- x2).to_string());
+ assertEqual(string("$123.45"), (- x3).to_string());
+ assertEqual(string("DM -123.45"), (- x4).to_string());
+ assertEqual(string("DM 123.45"), (- x5).to_string());
+ assertEqual(string("DM 123.45"), (- x6).to_string());
+ assertEqual(string("-123.45 euro"), (- x7).to_string());
+ assertEqual(string("123.45 euro"), (- x8).to_string());
+ assertEqual(string("-123.45€"), (- x9).to_string());
+ assertEqual(string("123.45€"), (- x10).to_string());
+
+ assertEqual(amount_t("$-123.45"), x1.negated());
+ assertEqual(amount_t("$123.45"), x2.negated());
+ assertEqual(amount_t("$123.45"), x3.negated());
+
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+ assertValid(x5);
+ assertValid(x6);
+ assertValid(x7);
+ assertValid(x8);
+ assertValid(x9);
+ assertValid(x10);
+}
+
+void AmountTestCase::testAbs()
+{
+ amount_t x0;
+ amount_t x1(-1234L);
+ amount_t x2(1234L);
+
+ assertThrow(x0.abs(), amount_error);
+ assertEqual(amount_t(1234L), x1.abs());
+ assertEqual(amount_t(1234L), x2.abs());
+
+ assertValid(x0);
+ assertValid(x1);
+ assertValid(x2);
+}
+
+void AmountTestCase::testCommodityAbs()
+{
+ amount_t x1("$-1234.56");
+ amount_t x2("$1234.56");
+
+ assertEqual(amount_t("$1234.56"), x1.abs());
+ assertEqual(amount_t("$1234.56"), x2.abs());
+
+ assertValid(x1);
+ assertValid(x2);
+}
+
+#ifndef NOT_FOR_PYTHON
+#if 0
+void AmountTestCase::testReduction()
+{
+ amount_t x0;
+ amount_t x1("60s");
+ amount_t x2("600s");
+ amount_t x3("6000s");
+ amount_t x4("360000s");
+ amount_t x5("10m"); // 600s
+ amount_t x6("100m"); // 6000s
+ amount_t x7("1000m"); // 60000s
+ amount_t x8("10000m"); // 600000s
+ amount_t x9("10h"); // 36000s
+ amount_t x10("100h"); // 360000s
+ amount_t x11("1000h"); // 3600000s
+ amount_t x12("10000h"); // 36000000s
+
+ assertThrow(x0.reduce(), amount_error);
+ assertThrow(x0.unreduce(), amount_error);
+ assertEqual(x2, x5.reduce());
+ assertEqual(x3, x6.reduce());
+ assertEqual(x10, x4.reduce());
+ assertEqual(string("100.0h"), x4.unreduce().to_string());
+}
+#endif
+#endif // NOT_FOR_PYTHON
+
+void AmountTestCase::testSign()
+{
+ amount_t x0;
+ amount_t x1("0.0000000000000000000000000000000000001");
+ amount_t x2("-0.0000000000000000000000000000000000001");
+ amount_t x3("1");
+ amount_t x4("-1");
+
+ assertThrow(x0.sign(), amount_error);
+ assertTrue(x1.sign() > 0);
+ assertTrue(x2.sign() < 0);
+ assertTrue(x3.sign() > 0);
+ assertTrue(x4.sign() < 0);
+
+ assertValid(x0);
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+}
+
+void AmountTestCase::testCommoditySign()
+{
+ amount_t x1(internalAmount("$0.0000000000000000000000000000000000001"));
+ amount_t x2(internalAmount("$-0.0000000000000000000000000000000000001"));
+ amount_t x3("$1");
+ amount_t x4("$-1");
+
+ assertTrue(x1.sign() != 0);
+ assertTrue(x2.sign() != 0);
+ assertTrue(x3.sign() > 0);
+ assertTrue(x4.sign() < 0);
+
+ assertValid(x1);
+ assertValid(x2);
+ assertValid(x3);
+ assertValid(x4);
+}
+
+void AmountTestCase::testTruth()
+{
+ amount_t x0;
+ amount_t x1("1234");
+ amount_t x2("1234.56");
+
+#ifndef NOT_FOR_PYTHON
+ assertThrow(x0.operator bool(), amount_error);
+#endif // NOT_FOR_PYTHON
+
+ assertTrue(x1);
+ assertTrue(x2);
+
+ assertValid(x0);
+ assertValid(x1);
+ assertValid(x2);
+}
+
+void AmountTestCase::testCommodityTruth()
+{
+ amount_t x1("$1234");
+ amount_t x2("$1234.56");
+
+ if (x1)
+ assertTrue(true);
+
+ if (x2)
+ assertTrue(true);
+
+ assertValid(x1);
+ assertValid(x2);
+}
+
+void AmountTestCase::testForZero()
+{
+ amount_t x0;
+ amount_t x1("0.000000000000000000001");
+
+ assertTrue(x1);
+ assertThrow(x0.is_zero(), amount_error);
+ assertThrow(x0.is_realzero(), amount_error);
+ assertFalse(x1.is_zero());
+ assertFalse(x1.is_realzero());
+
+ assertValid(x0);
+ assertValid(x1);
+}
+
+void AmountTestCase::testCommodityForZero()
+{
+ amount_t x1(internalAmount("$0.000000000000000000001"));
+
+ assertTrue(x1); // an internal amount never betrays its precision
+ assertFalse(x1.is_zero());
+ assertFalse(x1.is_realzero());
+
+ assertValid(x1);
+}
+
+void AmountTestCase::testIntegerConversion()
+{
+ amount_t x0;
+ amount_t x1(123456L);
+ amount_t x2("12345682348723487324");
+
+ assertThrow(x0.to_long(), amount_error);
+ assertThrow(x0.to_double(), amount_error);
+ assertFalse(x2.fits_in_long());
+ assertEqual(123456L, x1.to_long());
+ assertEqual(123456.0, x1.to_double());
+ assertEqual(string("123456"), x1.to_string());
+ assertEqual(string("123456"), x1.quantity_string());
+
+ assertValid(x1);
+}
+
+void AmountTestCase::testFractionalConversion()
+{
+ amount_t x1("1234.56");
+ amount_t x2("1234.5683787634678348734");
+
+ assertEqual(1235L, x1.to_long());
+ assertEqual(1234.56, x1.to_double());
+ assertEqual(string("1234.56"), x1.to_string());
+ assertEqual(string("1234.56"), x1.quantity_string());
+
+ assertValid(x1);
+}
+
+void AmountTestCase::testCommodityConversion()
+{
+ amount_t x1("$1234.56");
+
+ assertEqual(1235L, x1.to_long());
+ assertEqual(1234.56, x1.to_double());
+ assertEqual(string("$1234.56"), x1.to_string());
+ assertEqual(string("1234.56"), x1.quantity_string());
+
+ assertValid(x1);
+}
+
+#ifndef NOT_FOR_PYTHON
+
+void AmountTestCase::testPrinting()
+{
+ amount_t x0;
+ amount_t x1("982340823.380238098235098235098235098");
+
+ {
+ std::ostringstream bufstr;
+ x0.print(bufstr);
+ assertEqual(std::string("<null>"), bufstr.str());
+ }
+
+ {
+ std::ostringstream bufstr;
+ x1.print(bufstr);
+
+ assertEqual(std::string("982340823.380238098235098235098235098"),
+ bufstr.str());
+ }
+
+ assertValid(x0);
+ assertValid(x1);
+}
+
+void AmountTestCase::testCommodityPrinting()
+{
+ amount_t x1(internalAmount("$982340823.386238098235098235098235098"));
+ amount_t x2("$982340823.38");
+
+ {
+ std::ostringstream bufstr;
+ x1.print(bufstr);
+
+ assertEqual(std::string("$982340823.386238098235098235098235098"),
+ bufstr.str());
+ }
+
+ {
+ std::ostringstream bufstr;
+ (x1 * x2).print(bufstr);
+
+ assertEqual(std::string("$964993493285024293.18099172508158508135413499124"),
+ bufstr.str());
+ }
+
+ {
+ std::ostringstream bufstr;
+ (x2 * x1).print(bufstr);
+
+ assertEqual(std::string("$964993493285024293.18"), bufstr.str());
+ }
+
+ assertValid(x1);
+ assertValid(x2);
+}
+
+#endif // NOT_FOR_PYTHON
diff --git a/test/unit/t_amount.h b/test/unit/t_amount.h
new file mode 100644
index 00000000..3d63b2d7
--- /dev/null
+++ b/test/unit/t_amount.h
@@ -0,0 +1,105 @@
+#ifndef _T_AMOUNT_H
+#define _T_AMOUNT_H
+
+#include "UnitTests.h"
+
+class AmountTestCase : public CPPUNIT_NS::TestCase
+{
+ CPPUNIT_TEST_SUITE(AmountTestCase);
+
+ CPPUNIT_TEST(testConstructors);
+ CPPUNIT_TEST(testCommodityConstructors);
+ CPPUNIT_TEST(testParser);
+ CPPUNIT_TEST(testAssignment);
+ CPPUNIT_TEST(testCommodityAssignment);
+ CPPUNIT_TEST(testEquality);
+ CPPUNIT_TEST(testCommodityEquality);
+ CPPUNIT_TEST(testComparisons);
+ CPPUNIT_TEST(testCommodityComparisons);
+ CPPUNIT_TEST(testIntegerAddition);
+ CPPUNIT_TEST(testFractionalAddition);
+ CPPUNIT_TEST(testCommodityAddition);
+ CPPUNIT_TEST(testIntegerSubtraction);
+ CPPUNIT_TEST(testFractionalSubtraction);
+ CPPUNIT_TEST(testCommoditySubtraction);
+ CPPUNIT_TEST(testIntegerMultiplication);
+ CPPUNIT_TEST(testFractionalMultiplication);
+ CPPUNIT_TEST(testCommodityMultiplication);
+ CPPUNIT_TEST(testIntegerDivision);
+ CPPUNIT_TEST(testFractionalDivision);
+ CPPUNIT_TEST(testCommodityDivision);
+ CPPUNIT_TEST(testNegation);
+ CPPUNIT_TEST(testCommodityNegation);
+ CPPUNIT_TEST(testAbs);
+ CPPUNIT_TEST(testCommodityAbs);
+#if 0
+ CPPUNIT_TEST(testReduction);
+#endif
+ CPPUNIT_TEST(testSign);
+ CPPUNIT_TEST(testCommoditySign);
+ CPPUNIT_TEST(testTruth);
+ CPPUNIT_TEST(testCommodityTruth);
+ CPPUNIT_TEST(testForZero);
+ CPPUNIT_TEST(testCommodityForZero);
+ CPPUNIT_TEST(testIntegerConversion);
+ CPPUNIT_TEST(testFractionalConversion);
+ CPPUNIT_TEST(testCommodityConversion);
+ CPPUNIT_TEST(testPrinting);
+ CPPUNIT_TEST(testCommodityPrinting);
+
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ AmountTestCase() {}
+ virtual ~AmountTestCase() {}
+
+ virtual void setUp();
+ virtual void tearDown();
+
+ void testConstructors();
+ void testCommodityConstructors();
+ void testParser();
+ void testAssignment();
+ void testCommodityAssignment();
+ void testEquality();
+ void testCommodityEquality();
+ void testComparisons();
+ void testCommodityComparisons();
+ void testIntegerAddition();
+ void testFractionalAddition();
+ void testCommodityAddition();
+ void testIntegerSubtraction();
+ void testFractionalSubtraction();
+ void testCommoditySubtraction();
+ void testIntegerMultiplication();
+ void testFractionalMultiplication();
+ void testCommodityMultiplication();
+ void testIntegerDivision();
+ void testFractionalDivision();
+ void testCommodityDivision();
+ void testNegation();
+ void testCommodityNegation();
+ void testAbs();
+ void testCommodityAbs();
+ void testFractionalRound();
+ void testCommodityRound();
+ void testCommodityDisplayRound();
+ void testReduction();
+ void testSign();
+ void testCommoditySign();
+ void testTruth();
+ void testCommodityTruth();
+ void testForZero();
+ void testCommodityForZero();
+ void testIntegerConversion();
+ void testFractionalConversion();
+ void testCommodityConversion();
+ void testPrinting();
+ void testCommodityPrinting();
+
+private:
+ AmountTestCase(const AmountTestCase &copy);
+ void operator=(const AmountTestCase &copy);
+};
+
+#endif // _T_AMOUNT_H
diff --git a/test/unit/t_balance.cc b/test/unit/t_balance.cc
new file mode 100644
index 00000000..c7d633b8
--- /dev/null
+++ b/test/unit/t_balance.cc
@@ -0,0 +1,29 @@
+#include <system.hh>
+
+#include "t_balance.h"
+
+#include "utils.h"
+#include "amount.h"
+
+using namespace ledger;
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(BalanceTestCase, "math");
+
+void BalanceTestCase::setUp()
+{
+ times_initialize();
+ amount_t::initialize();
+
+ // Cause the display precision for dollars to be initialized to 2.
+ amount_t x1("$1.00");
+ assertTrue(x1);
+
+ amount_t::stream_fullstrings = true; // make reports from UnitTests accurate
+}
+
+void BalanceTestCase::tearDown()
+{
+ amount_t::stream_fullstrings = false;
+ amount_t::shutdown();
+ times_shutdown();
+}
diff --git a/test/unit/t_balance.h b/test/unit/t_balance.h
new file mode 100644
index 00000000..8b8ce1b7
--- /dev/null
+++ b/test/unit/t_balance.h
@@ -0,0 +1,28 @@
+#ifndef _T_BALANCE_H
+#define _T_BALANCE_H
+
+#include "UnitTests.h"
+
+class BalanceTestCase : public CPPUNIT_NS::TestCase
+{
+ CPPUNIT_TEST_SUITE(BalanceTestCase);
+
+ //CPPUNIT_TEST(testConstructors);
+
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ BalanceTestCase() {}
+ virtual ~BalanceTestCase() {}
+
+ virtual void setUp();
+ virtual void tearDown();
+
+ //void testConstructors();
+
+private:
+ BalanceTestCase(const BalanceTestCase &copy);
+ void operator=(const BalanceTestCase &copy);
+};
+
+#endif // _T_BALANCE_H
diff --git a/test/unit/t_commodity.cc b/test/unit/t_commodity.cc
new file mode 100644
index 00000000..3d84ead6
--- /dev/null
+++ b/test/unit/t_commodity.cc
@@ -0,0 +1,106 @@
+#include <system.hh>
+
+#include "t_commodity.h"
+
+#include "amount.h"
+#include "commodity.h"
+
+using namespace ledger;
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CommodityTestCase, "math");
+
+void CommodityTestCase::setUp() {
+ times_initialize();
+ amount_t::initialize();
+ amount_t::stream_fullstrings = true;
+}
+
+void CommodityTestCase::tearDown() {
+ amount_t::shutdown();
+ times_shutdown();
+}
+
+void CommodityTestCase::testPriceHistory()
+{
+#ifndef NOT_FOR_PYTHON
+ datetime_t jan17_05;
+ datetime_t jan17_06;
+ datetime_t jan17_07;
+ datetime_t feb27_07;
+ datetime_t feb28_07;
+ datetime_t feb28_07sbm;
+ datetime_t mar01_07;
+ datetime_t apr15_07;
+#endif // NOT_FOR_PYTHON
+
+ jan17_05 = parse_datetime("2005/01/17 00:00:00");
+ jan17_06 = parse_datetime("2006/01/17 00:00:00");
+ jan17_07 = parse_datetime("2007/01/17 00:00:00");
+ feb27_07 = parse_datetime("2007/02/27 18:00:00");
+ feb28_07 = parse_datetime("2007/02/28 06:00:00");
+ feb28_07sbm = parse_datetime("2007/02/28 11:59:59");
+ mar01_07 = parse_datetime("2007/03/01 00:00:00");
+ apr15_07 = parse_datetime("2007/04/15 13:00:00");
+
+ amount_t x0;
+ amount_t x1("100.10 AAPL");
+
+ assertThrow(x0.value(), amount_error);
+ assertFalse(x1.value());
+
+ // Commodities cannot be constructed by themselves, since a great deal
+ // of their state depends on how they were seen to be used.
+ commodity_t& aapl(x1.commodity());
+
+ aapl.add_price(jan17_07, amount_t("$10.20"));
+ aapl.add_price(feb27_07, amount_t("$13.40"));
+ aapl.add_price(feb28_07, amount_t("$18.33"));
+ aapl.add_price(feb28_07sbm, amount_t("$18.30"));
+ aapl.add_price(mar01_07, amount_t("$19.50"));
+ aapl.add_price(apr15_07, amount_t("$21.22"));
+ aapl.add_price(jan17_05, amount_t("EUR 23.00"));
+ aapl.add_price(jan17_06, amount_t("CAD 25.00"));
+
+ amount_t one_euro("EUR 1.00");
+ commodity_t& euro(one_euro.commodity());
+
+ euro.add_price(feb27_07, amount_t("CAD 1.40"));
+ euro.add_price(jan17_05, amount_t("$0.78"));
+
+ amount_t one_cad("CAD 1.00");
+ commodity_t& cad(one_cad.commodity());
+
+ cad.add_price(jan17_06, amount_t("$1.11"));
+
+#ifndef NOT_FOR_PYTHON
+ optional<amount_t> amt = x1.value(false, feb28_07sbm);
+ assertTrue(amt);
+ assertEqual(amount_t("$1831.83"), *amt);
+
+ amt = x1.value(false, CURRENT_TIME());
+ assertTrue(amt);
+ assertEqual(string("$2124.12"), amt->to_string());
+#ifdef INTEGER_MATH
+ assertEqual(string("$2124.12"), amt->to_fullstring());
+#else
+ assertEqual(string("$2124.122"), amt->to_fullstring());
+#endif
+
+ amt = x1.value(false, CURRENT_TIME(), euro);
+ assertTrue(amt);
+ assertEqual(string("EUR 1366.87"), amt->rounded().to_string());
+
+ // Add a newer Euro pricing
+ aapl.add_price(jan17_07, amount_t("EUR 23.00"));
+
+ amt = x1.value(false, CURRENT_TIME(), euro);
+ assertTrue(amt);
+ assertEqual(string("EUR 2302.30"), amt->to_string());
+
+ amt = x1.value(false, CURRENT_TIME(), cad);
+ assertTrue(amt);
+ assertEqual(string("CAD 3223.22"), amt->to_string());
+#endif // NOT_FOR_PYTHON
+
+ assertValid(x1);
+}
diff --git a/test/unit/t_commodity.h b/test/unit/t_commodity.h
new file mode 100644
index 00000000..1dadb450
--- /dev/null
+++ b/test/unit/t_commodity.h
@@ -0,0 +1,28 @@
+#ifndef _T_COMMMODITY_H
+#define _T_COMMMODITY_H
+
+#include "UnitTests.h"
+
+class CommodityTestCase : public CPPUNIT_NS::TestCase
+{
+ CPPUNIT_TEST_SUITE(CommodityTestCase);
+
+ CPPUNIT_TEST(testPriceHistory);
+
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ CommodityTestCase() {}
+ virtual ~CommodityTestCase() {}
+
+ virtual void setUp();
+ virtual void tearDown();
+
+ void testPriceHistory();
+
+private:
+ CommodityTestCase(const CommodityTestCase &copy);
+ void operator=(const CommodityTestCase &copy);
+};
+
+#endif // _T_COMMMODITY_H
diff --git a/test/unit/t_expr.cc b/test/unit/t_expr.cc
new file mode 100644
index 00000000..b5865948
--- /dev/null
+++ b/test/unit/t_expr.cc
@@ -0,0 +1,332 @@
+#include <system.hh>
+
+#include "t_expr.h"
+
+#include "expr.h"
+#include "predicate.h"
+#include "query.h"
+#include "op.h"
+
+using namespace ledger;
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ValueExprTestCase, "expr");
+
+void ValueExprTestCase::setUp()
+{
+ times_initialize();
+ amount_t::initialize();
+}
+
+void ValueExprTestCase::tearDown()
+{
+ amount_t::shutdown();
+ times_shutdown();
+}
+
+// 1. foo and bar
+// 2. 'foo and bar'
+// 3. (foo and bar)
+// 4. ( foo and bar )
+// 5. '( foo and' bar)
+// 6. =foo and bar
+// 7. ='foo and bar'
+// 8. 'expr foo and bar'
+// 9. expr 'foo and bar'
+// 10. expr foo and bar
+// 11. foo and bar or baz
+// 12. foo and bar | baz
+// 13. foo and bar |baz
+// 14. foo and bar| baz
+// 15. foo and bar|baz
+// 16. foo 'and bar|baz'
+
+void ValueExprTestCase::testPredicateTokenizer1()
+{
+ value_t args;
+ args.push_back(string_value("foo"));
+ args.push_back(string_value("and"));
+ args.push_back(string_value("bar"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer2()
+{
+ value_t args;
+ args.push_back(string_value("foo and bar"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer3()
+{
+ value_t args;
+ args.push_back(string_value("(foo"));
+ args.push_back(string_value("and"));
+ args.push_back(string_value("bar)"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::LPAREN, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::RPAREN, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer4()
+{
+ value_t args;
+ args.push_back(string_value("("));
+ args.push_back(string_value("foo"));
+ args.push_back(string_value("and"));
+ args.push_back(string_value("bar"));
+ args.push_back(string_value(")"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::LPAREN, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::RPAREN, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer5()
+{
+ value_t args;
+ args.push_back(string_value("( foo and"));
+ args.push_back(string_value("bar)"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::LPAREN, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::RPAREN, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer6()
+{
+ value_t args;
+ args.push_back(string_value("=foo"));
+ args.push_back(string_value("and"));
+ args.push_back(string_value("bar"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TOK_EQ, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer7()
+{
+ value_t args;
+ args.push_back(string_value("=foo and bar"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TOK_EQ, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer8()
+{
+ value_t args;
+ args.push_back(string_value("expr foo and bar"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TOK_EXPR, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer9()
+{
+ value_t args;
+ args.push_back(string_value("expr"));
+ args.push_back(string_value("foo and bar"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TOK_EXPR, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer10()
+{
+ value_t args;
+ args.push_back(string_value("expr"));
+ args.push_back(string_value("foo"));
+ args.push_back(string_value("and"));
+ args.push_back(string_value("bar"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TOK_EXPR, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer11()
+{
+ value_t args;
+ args.push_back(string_value("foo"));
+ args.push_back(string_value("and"));
+ args.push_back(string_value("bar"));
+ args.push_back(string_value("or"));
+ args.push_back(string_value("baz"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_OR, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer12()
+{
+ value_t args;
+ args.push_back(string_value("foo"));
+ args.push_back(string_value("and"));
+ args.push_back(string_value("bar"));
+ args.push_back(string_value("|"));
+ args.push_back(string_value("baz"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_OR, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer13()
+{
+ value_t args;
+ args.push_back(string_value("foo"));
+ args.push_back(string_value("and"));
+ args.push_back(string_value("bar"));
+ args.push_back(string_value("|baz"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_OR, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer14()
+{
+ value_t args;
+ args.push_back(string_value("foo"));
+ args.push_back(string_value("and"));
+ args.push_back(string_value("bar|"));
+ args.push_back(string_value("baz"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_OR, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer15()
+{
+ value_t args;
+ args.push_back(string_value("foo"));
+ args.push_back(string_value("and"));
+ args.push_back(string_value("bar|baz"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_OR, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
+
+void ValueExprTestCase::testPredicateTokenizer16()
+{
+ value_t args;
+ args.push_back(string_value("foo"));
+ args.push_back(string_value("and bar|baz"));
+
+#ifndef NOT_FOR_PYTHON
+ query_t::lexer_t tokens(args.begin(), args.end());
+
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TOK_OR, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind);
+ assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind);
+#endif
+}
diff --git a/test/unit/t_expr.h b/test/unit/t_expr.h
new file mode 100644
index 00000000..2f22db3d
--- /dev/null
+++ b/test/unit/t_expr.h
@@ -0,0 +1,60 @@
+#ifndef _T_EXPR_H
+#define _T_EXPR_H
+
+#include "UnitTests.h"
+
+class ValueExprTestCase : public CPPUNIT_NS::TestCase
+{
+ CPPUNIT_TEST_SUITE(ValueExprTestCase);
+
+ //CPPUNIT_TEST(testConstructors);
+ CPPUNIT_TEST(testPredicateTokenizer1);
+ CPPUNIT_TEST(testPredicateTokenizer2);
+ CPPUNIT_TEST(testPredicateTokenizer3);
+ CPPUNIT_TEST(testPredicateTokenizer4);
+ CPPUNIT_TEST(testPredicateTokenizer5);
+ CPPUNIT_TEST(testPredicateTokenizer6);
+ CPPUNIT_TEST(testPredicateTokenizer7);
+ CPPUNIT_TEST(testPredicateTokenizer8);
+ CPPUNIT_TEST(testPredicateTokenizer9);
+ CPPUNIT_TEST(testPredicateTokenizer10);
+ CPPUNIT_TEST(testPredicateTokenizer11);
+ CPPUNIT_TEST(testPredicateTokenizer12);
+ CPPUNIT_TEST(testPredicateTokenizer13);
+ CPPUNIT_TEST(testPredicateTokenizer14);
+ CPPUNIT_TEST(testPredicateTokenizer15);
+ CPPUNIT_TEST(testPredicateTokenizer16);
+
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ ValueExprTestCase() {}
+ virtual ~ValueExprTestCase() {}
+
+ virtual void setUp();
+ virtual void tearDown();
+
+ //void testConstructors();
+ void testPredicateTokenizer1();
+ void testPredicateTokenizer2();
+ void testPredicateTokenizer3();
+ void testPredicateTokenizer4();
+ void testPredicateTokenizer5();
+ void testPredicateTokenizer6();
+ void testPredicateTokenizer7();
+ void testPredicateTokenizer8();
+ void testPredicateTokenizer9();
+ void testPredicateTokenizer10();
+ void testPredicateTokenizer11();
+ void testPredicateTokenizer12();
+ void testPredicateTokenizer13();
+ void testPredicateTokenizer14();
+ void testPredicateTokenizer15();
+ void testPredicateTokenizer16();
+
+private:
+ ValueExprTestCase(const ValueExprTestCase &copy);
+ void operator=(const ValueExprTestCase &copy);
+};
+
+#endif // _T_EXPR_H
diff --git a/test/unit/t_times.cc b/test/unit/t_times.cc
new file mode 100644
index 00000000..d8a67b43
--- /dev/null
+++ b/test/unit/t_times.cc
@@ -0,0 +1,166 @@
+#include <system.hh>
+
+#include "t_times.h"
+
+#include "utils.h"
+#include "times.h"
+
+using namespace ledger;
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(DateTimeTestCase, "util");
+
+void DateTimeTestCase::setUp()
+{
+ times_initialize();
+}
+
+void DateTimeTestCase::tearDown()
+{
+ times_shutdown();
+}
+
+void DateTimeTestCase::testConstructors()
+{
+#ifndef NOT_FOR_PYTHON
+ std::time_t now = std::time(NULL);
+ struct tm * moment = std::localtime(&now);
+ std::time_t localMoment = std::mktime(moment);
+#endif // NOT_FOR_PYTHON
+
+#ifndef NOT_FOR_PYTHON
+ date_t d0;
+ date_t d1;
+ datetime_t d3;
+ date_t d4;
+ date_t d5;
+ date_t d6;
+ date_t d7;
+ date_t d8;
+ date_t d9;
+
+#if 0
+ date_t d10;
+ date_t d11;
+ date_t d12;
+ date_t d13;
+ date_t d14;
+ datetime_t d15;
+#endif
+#endif // NOT_FOR_PYTHON
+
+ d1 = parse_date("1990/01/01");
+#ifndef NOT_FOR_PYTHON
+ d3 = boost::posix_time::from_time_t(localMoment);
+#endif // NOT_FOR_PYTHON
+ d4 = parse_date("2006/12/25");
+ d5 = parse_date("12/25");
+ d6 = parse_date("2006.12.25");
+ d7 = parse_date("12.25");
+ d8 = parse_date("2006-12-25");
+ d9 = parse_date("12-25");
+
+#ifndef NOT_FOR_PYTHON
+#if 0
+ d10 = parse_date("tue");
+ d11 = parse_date("tuesday");
+ d12 = parse_date("feb");
+ d13 = parse_date("february");
+ d14 = parse_date("2006");
+ d15 = d3;
+#endif
+#endif // NOT_FOR_PYTHON
+
+#ifndef NOT_FOR_PYTHON
+ assertTrue(d0.is_not_a_date());
+ assertFalse(d1.is_not_a_date());
+ assertFalse(d4.is_not_a_date());
+#endif // NOT_FOR_PYTHON
+
+ assertTrue(CURRENT_DATE() > d1);
+ assertTrue(CURRENT_DATE() > d4);
+
+#ifndef NOT_FOR_PYTHON
+#if 0
+ assertEqual(d3, d15);
+#endif
+#endif // NOT_FOR_PYTHON
+ assertEqual(d4, d6);
+ assertEqual(d4, d8);
+ assertEqual(d5, d7);
+ assertEqual(d5, d9);
+#ifndef NOT_FOR_PYTHON
+#if 0
+ assertEqual(d10, d11);
+ assertEqual(d12, d13);
+
+ assertThrow(parse_date("2007/02/29"), boost::gregorian::bad_day_of_month);
+ //assertThrow(parse_date("2007/13/01"), datetime_error);
+ //assertThrow(parse_date("2007/00/01"), datetime_error);
+ assertThrow(parse_date("2007/01/00"), boost::gregorian::bad_day_of_month);
+ //assertThrow(parse_date("2007/00/00"), boost::gregorian::bad_day_of_month);
+ //assertThrow(parse_date("2007/05/32"), boost::gregorian::bad_day_of_month);
+
+ assertThrow(parse_date("2006x/12/25"), datetime_error);
+ assertThrow(parse_date("2006/12x/25"), datetime_error);
+ assertThrow(parse_date("2006/12/25x"), datetime_error);
+
+ assertThrow(parse_date("feb/12/25"), datetime_error);
+ assertThrow(parse_date("2006/mon/25"), datetime_error);
+ assertThrow(parse_date("2006/12/web"), datetime_error);
+
+ assertThrow(parse_date("12*25"), datetime_error);
+
+ assertThrow(parse_date("tuf"), datetime_error);
+ assertThrow(parse_date("tufsday"), datetime_error);
+ assertThrow(parse_date("fec"), datetime_error);
+ assertThrow(parse_date("fecruary"), datetime_error);
+ assertThrow(parse_date("207x"), datetime_error);
+ assertThrow(parse_date("hello"), datetime_error);
+
+ d1 = parse_date("2002-02-02");
+ d1 = parse_date("2002/02/02");
+ d1 = parse_date("2002.02.02");
+ d1 = parse_date("02-02-2002");
+ d1 = parse_date("02/02/2002");
+ d1 = parse_date("02.02.2002");
+ d1 = parse_date("02-02-02");
+ d1 = parse_date("02/02/02");
+ d1 = parse_date("02.02.02");
+ d1 = parse_date("02-02");
+ d1 = parse_date("02/02");
+ d1 = parse_date("02.02");
+ d1 = parse_date("20020202");
+ d1 = parse_date("20020202T023318");
+ d1 = parse_date("20020202T023318-0700");
+ d1 = parse_date("20020202T023318-0100");
+ d1 = parse_date("02-Feb-2002");
+ d1 = parse_date("2002-Feb-02");
+ d1 = parse_date("02 Feb 2002");
+ d1 = parse_date("02-Feb-2002");
+ d1 = parse_date("02 February 2002");
+ d1 = parse_date("02-February-2002");
+ d1 = parse_date("2002 Feb 02");
+ d1 = parse_date("2002-Feb-02");
+ d1 = parse_date("2002 February 02");
+ d1 = parse_date("2002-February-02");
+ d1 = parse_date("02 Feb");
+ d1 = parse_date("02-Feb");
+ d1 = parse_date("02 February");
+ d1 = parse_date("02-February");
+ d1 = parse_date("Feb 02");
+ d1 = parse_date("Feb-02");
+ d1 = parse_date("February 02");
+ d1 = parse_date("February-02");
+ d1 = parse_date("Feb 02, 2002");
+ d1 = parse_date("February 02, 2002");
+ d1 = parse_date("2002-02-02 12:00:00");
+ d1 = parse_date("2002-02-02 12:00:00 AM");
+ d1 = parse_date("2002-02-02 12:00 AM");
+ d1 = parse_date("2002-02-02 12:00AM");
+ d1 = parse_date("2002-02-02 12p");
+ d1 = parse_date("2002-02-02 12a");
+
+ assertValid(d1);
+#endif // NOT_FOR_PYTHON
+#endif
+}
diff --git a/test/unit/t_times.h b/test/unit/t_times.h
new file mode 100644
index 00000000..5bbadf21
--- /dev/null
+++ b/test/unit/t_times.h
@@ -0,0 +1,28 @@
+#ifndef _T_TIMES_H
+#define _T_TIMES_H
+
+#include "UnitTests.h"
+
+class DateTimeTestCase : public CPPUNIT_NS::TestCase
+{
+ CPPUNIT_TEST_SUITE(DateTimeTestCase);
+
+ CPPUNIT_TEST(testConstructors);
+
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ DateTimeTestCase() {}
+ virtual ~DateTimeTestCase() {}
+
+ virtual void setUp();
+ virtual void tearDown();
+
+ void testConstructors();
+
+private:
+ DateTimeTestCase(const DateTimeTestCase &copy);
+ void operator=(const DateTimeTestCase &copy);
+};
+
+#endif /* _T_TIMES_H */
diff --git a/test/unit/t_utils.cc b/test/unit/t_utils.cc
new file mode 100644
index 00000000..6c63359c
--- /dev/null
+++ b/test/unit/t_utils.cc
@@ -0,0 +1,6 @@
+#include <system.hh>
+
+#include "t_utils.h"
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(UtilitiesTestCase, "util");
+
diff --git a/test/unit/t_utils.h b/test/unit/t_utils.h
new file mode 100644
index 00000000..4520c580
--- /dev/null
+++ b/test/unit/t_utils.h
@@ -0,0 +1,28 @@
+#ifndef _T_UTILS_H
+#define _T_UTILS_H
+
+#include "UnitTests.h"
+
+class UtilitiesTestCase : public CPPUNIT_NS::TestCase
+{
+ CPPUNIT_TEST_SUITE(UtilitiesTestCase);
+
+ //CPPUNIT_TEST(testConstructors);
+
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ UtilitiesTestCase() {}
+ virtual ~UtilitiesTestCase() {}
+
+ //virtual void setUp();
+ //virtual void tearDown();
+
+ //void testConstructors();
+
+private:
+ UtilitiesTestCase(const UtilitiesTestCase &copy);
+ void operator=(const UtilitiesTestCase &copy);
+};
+
+#endif /* _T_UTILS_H */
diff --git a/tests/amounts.h b/tests/amounts.h
deleted file mode 100644
index a72e57d2..00000000
--- a/tests/amounts.h
+++ /dev/null
@@ -1,169 +0,0 @@
-#ifndef __TESTAMOUNT_H
-#define __TESTAMOUNT_H
-
-#include <cxxtest/TestSuite.h>
-
-#include <amount.h>
-
-using namespace ledger;
-
-class TestAmount : public CxxTest::TestSuite
-{
-public:
- void testCreateAmountWithoutCommodityFromInteger()
- {
- amount_t a((long int)42);
- TS_ASSERT_EQUALS("", a.commodity().symbol());
- TS_ASSERT_EQUALS("", a.commodity().base_symbol());
- TS_ASSERT_EQUALS("42", a.quantity_string());
- }
-
- void testCreateAmountWithoutCommodity()
- {
- amount_t a("42");
- TS_ASSERT_EQUALS("", a.commodity().symbol());
- TS_ASSERT_EQUALS("", a.commodity().base_symbol());
- TS_ASSERT_EQUALS("42", a.quantity_string());
- }
-
- void testCreateAmountWithPrefixCommodity()
- {
- amount_t *a;
- a = new amount_t("$ 42");
- TS_ASSERT_EQUALS("$", a->commodity().symbol());
- TS_ASSERT_EQUALS("$", a->commodity().base_symbol());
- TS_ASSERT_EQUALS("42", a->quantity_string());
- }
-
- void testCreateAmountWithPostfixCommodity()
- {
- amount_t *a;
- a = new amount_t("42 GLD");
- TS_ASSERT_EQUALS("GLD", a->commodity().symbol());
- TS_ASSERT_EQUALS("GLD", a->commodity().base_symbol());
- TS_ASSERT_EQUALS("42", a->quantity_string());
- }
-
- void testCreateAmountWithPrefixCommodityContainingSpace()
- {
- amount_t *a;
- a = new amount_t("\"one dollar\" 42");
- TS_ASSERT_EQUALS("\"one dollar\"", a->commodity().symbol());
- TS_ASSERT_EQUALS("one dollar", a->commodity().base_symbol());
- TS_ASSERT_EQUALS("42", a->quantity_string());
- }
-
- void testCreateAmountWithPostfixCommodityContainingSpace()
- {
- amount_t *a;
- a = new amount_t("42 \"swedish crowns\"");
- TS_ASSERT_EQUALS("\"swedish crowns\"", a->commodity().symbol());
- TS_ASSERT_EQUALS("swedish crowns", a->commodity().base_symbol());
- TS_ASSERT_EQUALS("42", a->quantity_string());
- }
-
- void testCreateAmountWithDirectPrefixCommodity()
- {
- amount_t *a;
- a = new amount_t("$42");
- TS_ASSERT_EQUALS("$", a->commodity().symbol());
- TS_ASSERT_EQUALS("$", a->commodity().base_symbol());
- TS_ASSERT_EQUALS("42", a->quantity_string());
- }
-
- void testCreateAmountWithDirectPostfixCommodity()
- {
- amount_t *a;
- a = new amount_t("42GLD");
- TS_ASSERT_EQUALS("GLD", a->commodity().symbol());
- TS_ASSERT_EQUALS("GLD", a->commodity().base_symbol());
- TS_ASSERT_EQUALS("42", a->quantity_string());
- }
-
- void testCannotCreateAmountWithoutQuantity()
- {
- TS_ASSERT_THROWS(new amount_t("$"), amount_error*);
- }
-
- void testCreateBiiigIntegerAmount()
- {
- amount_t a("12345678901234567890123456789012345678901234567890");
- TS_ASSERT_EQUALS("12345678901234567890123456789012345678901234567890",
- a.quantity_string());
- }
-
- void testCreateBiiigDecimalAmount()
- {
- amount_t a("12345678.901234567890123456789012345678901234567890");
- TS_ASSERT_EQUALS("12345678.901234567890123456789012345678901234567890",
- a.quantity_string());
- }
-
- void testCreateCommodityAnnotatedWithEntry()
- {
- amount_t a("10 AAPL (entry 6)");
- TS_ASSERT_EQUALS("10", a.quantity_string());
- commodity_t c = a.commodity();
- TS_ASSERT_EQUALS("AAPL", c.symbol());
- TS_ASSERT_EQUALS("AAPL", c.base_symbol());
- TS_ASSERT(c.annotated);
- //TODO: check entry annotation
- }
-
- void testCreateCommodityAnnotatedWithEntry2()
- {
- amount_t *a = new amount_t("10 AAPL (entry 6)");
- TS_ASSERT_EQUALS("10", a->quantity_string());
- commodity_t c = a->commodity();
- TS_ASSERT_EQUALS("AAPL", c.symbol());
- TS_ASSERT_EQUALS("AAPL", c.base_symbol());
- TS_ASSERT(c.annotated);
- //TODO: check entry annotation
- }
-
- void testAddTwoAmountsWithoutCommodity()
- {
- amount_t a("6");
- amount_t b("9");
- TS_ASSERT_EQUALS(* new amount_t((long int)15), a+b);
- }
-
- void testAddTwoAmountsWithSameCommodity()
- {
- amount_t a("$ 6");
- amount_t b("$ 9");
- TS_ASSERT_EQUALS(* new amount_t("$ 15"), a+b);
- }
-
- void testCannotAddTwoAmountsWithDifferentCommodities()
- {
- amount_t a("$ 6");
- amount_t b("9 GLD");
- TS_ASSERT_THROWS(a+b, amount_error*);
- }
-
- void testCompareTwoAmountsWithSameCommodity()
- {
- amount_t a("6 SCOX");
- amount_t b("9 SCOX");
- TS_ASSERT(a < b);
- TS_ASSERT(a <= b);
- TS_ASSERT(!(a > b));
- TS_ASSERT(!(a >= b));
- TS_ASSERT(!(a == b));
- }
-
- void testCannotCompareTwoAmountsWithDifferentCommodities()
- {
- amount_t a("$ 6");
- amount_t b("9 GLD");
-
- TS_ASSERT_THROWS(a < b, amount_error*);
- TS_ASSERT_THROWS(a <= b, amount_error*);
- TS_ASSERT_THROWS(a > b, amount_error*);
- TS_ASSERT_THROWS(a >= b, amount_error*);
- TS_ASSERT(!(a == b));
- }
-};
-
-#endif // __TESTAMOUNT_H
diff --git a/tests/baseline/1001 b/tests/baseline/1001
deleted file mode 100644
index f570768a..00000000
--- a/tests/baseline/1001
+++ /dev/null
@@ -1 +0,0 @@
-Error: "tests/cases/1001.dat", line 10: Only one transaction with null amount allowed per entry
diff --git a/tests/baseline/1002 b/tests/baseline/1002
deleted file mode 100644
index 8ca4d8d4..00000000
--- a/tests/baseline/1002
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- xgain -20
- Liabilities:MasterCard
diff --git a/tests/baseline/1003 b/tests/baseline/1003
deleted file mode 100644
index 61e03c48..00000000
--- a/tests/baseline/1003
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- xtime -20
- Liabilities:MasterCard
diff --git a/tests/baseline/1004 b/tests/baseline/1004
deleted file mode 100644
index dbbfea17..00000000
--- a/tests/baseline/1004
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- xopti -20
- Liabilities:MasterCard
diff --git a/tests/baseline/1005 b/tests/baseline/1005
deleted file mode 100644
index 8541a38d..00000000
--- a/tests/baseline/1005
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- xgain 0
- Liabilities:MasterCard
diff --git a/tests/baseline/1006 b/tests/baseline/1006
deleted file mode 100644
index 0ea315f9..00000000
--- a/tests/baseline/1006
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- xtime 0
- Liabilities:MasterCard
diff --git a/tests/baseline/1007 b/tests/baseline/1007
deleted file mode 100644
index 40f2827a..00000000
--- a/tests/baseline/1007
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- xopti 0
- Liabilities:MasterCard
diff --git a/tests/baseline/1008 b/tests/baseline/1008
deleted file mode 100644
index 385151b2..00000000
--- a/tests/baseline/1008
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- xgain $-20.00
- Equity:Options
diff --git a/tests/baseline/1009 b/tests/baseline/1009
deleted file mode 100644
index 127ad02a..00000000
--- a/tests/baseline/1009
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- xtime $-20.00
- Equity:Options
diff --git a/tests/baseline/1010 b/tests/baseline/1010
deleted file mode 100644
index e408036b..00000000
--- a/tests/baseline/1010
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- xopti $-20.00
- Equity:Options
diff --git a/tests/baseline/1011 b/tests/baseline/1011
deleted file mode 100644
index 9c70db18..00000000
--- a/tests/baseline/1011
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- xgain 0
- Equity:Options
diff --git a/tests/baseline/1012 b/tests/baseline/1012
deleted file mode 100644
index 890005ab..00000000
--- a/tests/baseline/1012
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- xtime 0
- Equity:Options
diff --git a/tests/baseline/1013 b/tests/baseline/1013
deleted file mode 100644
index 1b7bb71e..00000000
--- a/tests/baseline/1013
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- xopti 0
- Equity:Options
diff --git a/tests/baseline/1014 b/tests/baseline/1014
deleted file mode 100644
index 384133b6..00000000
--- a/tests/baseline/1014
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- Capital Gains $-20.00
- Liabilities:MasterCard
diff --git a/tests/baseline/1015 b/tests/baseline/1015
deleted file mode 100644
index 46d5f454..00000000
--- a/tests/baseline/1015
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- time -20
- Liabilities:MasterCard
diff --git a/tests/baseline/1016 b/tests/baseline/1016
deleted file mode 100644
index 7fa39204..00000000
--- a/tests/baseline/1016
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- Brokerage:Options -20.00 COMP
- Liabilities:MasterCard
diff --git a/tests/baseline/1017 b/tests/baseline/1017
deleted file mode 100644
index 14b37f8b..00000000
--- a/tests/baseline/1017
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- Capital Gains 0
- Liabilities:MasterCard
diff --git a/tests/baseline/1018 b/tests/baseline/1018
deleted file mode 100644
index 9f3761f8..00000000
--- a/tests/baseline/1018
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- time 0
- Liabilities:MasterCard
diff --git a/tests/baseline/1019 b/tests/baseline/1019
deleted file mode 100644
index 10f14f4e..00000000
--- a/tests/baseline/1019
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- Brokerage:Options 0
- Liabilities:MasterCard
diff --git a/tests/baseline/1020 b/tests/baseline/1020
deleted file mode 100644
index f1547ca7..00000000
--- a/tests/baseline/1020
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- Expenses -20
- Liabilities:MasterCard
diff --git a/tests/baseline/1021 b/tests/baseline/1021
deleted file mode 100644
index 7e3fe64d..00000000
--- a/tests/baseline/1021
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 stock optionx
- Expenses 0
- Liabilities:MasterCard
diff --git a/tests/baseline/1022 b/tests/baseline/1022
deleted file mode 100644
index 953a3c02..00000000
--- a/tests/baseline/1022
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- Capital Gains $-20.00
- Equity:Options
diff --git a/tests/baseline/1023 b/tests/baseline/1023
deleted file mode 100644
index 62274097..00000000
--- a/tests/baseline/1023
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- time $-20.00
- Equity:Options
diff --git a/tests/baseline/1024 b/tests/baseline/1024
deleted file mode 100644
index 8272dfd9..00000000
--- a/tests/baseline/1024
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- Brokerage:Options -20.00 COMP
- Equity:Options
diff --git a/tests/baseline/1025 b/tests/baseline/1025
deleted file mode 100644
index 52dc8139..00000000
--- a/tests/baseline/1025
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- Capital Gains 0
- Equity:Options
diff --git a/tests/baseline/1026 b/tests/baseline/1026
deleted file mode 100644
index 5071338a..00000000
--- a/tests/baseline/1026
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- time 0
- Equity:Options
diff --git a/tests/baseline/1027 b/tests/baseline/1027
deleted file mode 100644
index 31d7c8ab..00000000
--- a/tests/baseline/1027
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- Brokerage:Options 45.60 COMP
- Equity:Options
diff --git a/tests/baseline/1028 b/tests/baseline/1028
deleted file mode 100644
index 8272dfd9..00000000
--- a/tests/baseline/1028
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- Brokerage:Options -20.00 COMP
- Equity:Options
diff --git a/tests/baseline/1029 b/tests/baseline/1029
deleted file mode 100644
index 31d7c8ab..00000000
--- a/tests/baseline/1029
+++ /dev/null
@@ -1,4 +0,0 @@
-
-2006/10/20 Stock option vesting schedule
- Brokerage:Options 45.60 COMP
- Equity:Options
diff --git a/tests/cases/1001.dat b/tests/cases/1001.dat
deleted file mode 100644
index c781fb4f..00000000
--- a/tests/cases/1001.dat
+++ /dev/null
@@ -1,10 +0,0 @@
-1.00s = 100c
-1.00G = 100s
-
-D 1.00G
-
-2006/03/14 Opening Balances
- Assets:Ebonheart 63869c
- Assets:Tajer 248720c
- Assets:Gruulmorg
- Equity:Gold
diff --git a/tests/cases/1002.dat b/tests/cases/1002.dat
deleted file mode 100644
index 8719b603..00000000
--- a/tests/cases/1002.dat
+++ /dev/null
@@ -1,25 +0,0 @@
-D $1,000.00
-
-A Liabilities:MasterCard
-
-@def foo(x)=x*1000
-
-2006/02/14 Buy
- Broker AAPL 10 @ $200.00 ; this is a little note [2006/10/10]
- Broker AAPL 10 @ $300.00
- Bank ; this is a comment
-
-2006/02/14 Sell
- Bank $2000.00 + $500.00
- Broker AAPL -5 [2005/10/20] {$200.0015} @ $500.00
- Capital Gains $-1500.00
-
-2005/10/20 Stock option vesting schedule
- Brokerage:Options (1.00 COMP {$10.00}*min((([2006/08/20]-[2005/10/20])/3600/24)*0.15, 5000))
- Equity:Options
-
-P 2006/02/27 00:00:00 COMP $15.00
-
-;2005/10/20 Stock option vesting schedule
-; Brokerage:Time (1+@now)
-; Equity:Time
diff --git a/tests/cases/1030.dat b/tests/cases/1030.dat
deleted file mode 100644
index 60fcac1c..00000000
--- a/tests/cases/1030.dat
+++ /dev/null
@@ -1,24 +0,0 @@
-2006/03/01 Basis
- Assets:Pool $1000
- (Shares) 1000 shares {$1.00}
- Equity
-
-P 2006/03/01 shares $1.00
-
-2006/03/10 Purchase
- (Payable:You) -500 shares {$1}
- (Shares) -500 shares
- Assets:Investment $500
- Income:Investments $-500
-
-2006/03/16 Growth
- Assets:Pool $500
- Income:Capital Gains
-
-P 2006/03/16 shares $1.50
-
-2006/03/16 Cash out
- (Payable:You) 250 shares {$1}
- (Shares) 250 shares
- Expenses:Investors
- Assets (- valueof({1 shares}) * 250)
diff --git a/tests/cases/1032.dat b/tests/cases/1032.dat
deleted file mode 100644
index 1b103f1d..00000000
--- a/tests/cases/1032.dat
+++ /dev/null
@@ -1,834 +0,0 @@
-i 2003/10/06 15:21:00 EDG fp_conv
-o 2003/10/06 15:47:53 retrieved documents from ACM and the Web
-i 2003/10/08 16:25:08 EDG fp_conv
-o 2003/10/08 17:10:50 read Steele document; need to print and implement
-i 2003/10/18 14:54:34 EDG fp_conv
-o 2003/10/18 16:56:59
-i 2003/10/18 23:50:34 EDG fp_conv
-o 2003/10/19 01:08:12
-i 2003/10/19 10:54:33 EDG fp_conv
-o 2003/10/19 12:41:56
-i 2003/10/19 16:21:07 EDG fp_conv
-o 2003/10/19 18:29:39
-i 2003/10/21 14:54:10 EDG fp_conv
-o 2003/10/21 18:07:07
-i 2003/10/21 22:44:17 EDG fp_conv
-o 2003/10/21 23:55:57
-i 2003/10/22 22:26:53 EDG fp_conv
-o 2003/10/22 23:22:49
-i 2003/10/23 02:44:00 EDG fp_conv
-o 2003/10/23 03:34:00
-i 2003/10/23 16:12:27 EDG fp_conv
-o 2003/10/23 17:39:08
-i 2003/10/26 10:32:16 ForumJobs Meeting
-o 2003/10/26 15:59:28
-i 2003/10/26 17:26:23 ForumJobs Meeting
-o 2003/10/26 17:57:52
-i 2003/10/27 16:02:10 EDG fp_conv
-o 2003/10/27 17:33:53
-i 2003/10/27 22:38:57 EDG fp_conv
-o 2003/10/28 23:37:51 Steele is working in C, with fgmp
-i 2003/10/28 12:13:46 EDG fp_conv
-o 2003/10/28 12:27:31 sought documents relating to MP math
-i 2003/10/28 16:14:41 EDG fp_conv
-o 2003/10/28 18:32:44 still need to implement mul/div/mod
-i 2003/10/29 22:18:23 EDG fp_conv
-o 2003/10/29 23:38:07
-i 2003/10/30 16:39:19 EDG fp_conv
-o 2003/10/30 17:18:07
-i 2003/10/30 23:33:14 EDG fp_conv
-o 2003/10/31 01:21:18
-i 2003/10/31 13:16:38 EDG fp_conv
-o 2003/10/31 15:01:32
-i 2003/10/31 16:49:51 EDG fp_conv
-o 2003/10/31 17:26:45
-i 2003/10/31 23:15:10 EDG fp_conv
-o 2003/11/01 00:48:11
-i 2003/11/01 12:50:49 EDG fp_conv
-o 2003/11/01 14:01:35
-i 2003/11/01 18:53:48 EDG fp_conv
-o 2003/11/01 19:16:41
-i 2003/11/02 21:50:36 EDG fp_conv
-o 2003/11/03 00:05:10
-i 2003/11/03 19:30:48 EDG fp_conv
-o 2003/11/03 21:44:02
-i 2003/11/04 19:55:44 EDG fp_conv
-o 2003/11/04 20:54:24
-i 2003/11/05 15:36:45 EDG fp_conv
-o 2003/11/05 18:35:36
-i 2003/11/06 16:23:41 EDG fp_conv
-o 2003/11/06 16:37:04
-i 2003/11/06 17:23:27 EDG fp_conv
-o 2003/11/06 17:37:22
-i 2003/11/07 00:02:44 EDG fp_conv
-o 2003/11/07 01:44:34
-i 2003/11/07 14:52:46 EDG fp_conv
-o 2003/11/07 15:07:55
-i 2003/11/07 17:16:59 EDG fp_conv
-o 2003/11/07 18:01:49
-i 2003/11/08 16:47:41 EDG fp_conv
-o 2003/11/08 17:25:38
-i 2003/11/09 15:25:01 EDG fp_conv
-o 2003/11/09 15:49:55
-i 2003/11/10 17:54:44 EDG fp_conv
-o 2003/11/10 18:43:49
-i 2003/11/11 15:02:51 EDG fp_conv
-o 2003/11/11 15:23:49
-i 2003/11/13 20:37:34 EDG fp_conv
-o 2003/11/13 21:24:47
-i 2003/11/14 01:23:47 EDG fp_conv
-o 2003/11/14 02:58:15
-i 2003/11/16 19:43:32 EDG fp_conv
-o 2003/11/16 20:13:59
-i 2003/11/16 21:37:30 EDG fp_conv
-o 2003/11/16 23:32:12
-i 2003/11/16 23:53:07 EDG fp_conv
-o 2003/11/17 00:10:06
-i 2003/11/19 01:14:33 EDG fp_conv
-o 2003/11/19 02:29:34
-i 2003/11/19 14:54:48 EDG fp_conv
-o 2003/11/19 18:27:36
-i 2003/11/19 22:49:09 EDG fp_conv
-o 2003/11/19 23:42:47
-i 2003/11/19 23:53:56 EDG fp_conv
-o 2003/11/20 00:22:53
-i 2003/11/23 00:27:28 EDG fp_conv
-o 2003/11/23 02:36:37
-i 2003/11/23 14:24:29 EDG fp_conv
-o 2003/11/23 14:46:21
-i 2003/11/23 15:23:12 EDG fp_conv
-o 2003/11/23 16:24:58
-i 2003/11/24 19:04:26 EDG fp_conv
-o 2003/11/24 20:40:45
-i 2003/11/24 21:13:32 EDG fp_conv
-o 2003/11/24 22:50:26
-i 2003/11/25 16:04:57 EDG fp_conv
-o 2003/11/25 19:16:07
-i 2003/11/25 20:01:32 EDG fp_conv
-o 2003/11/25 20:20:37
-i 2003/11/25 22:03:56 EDG fp_conv
-o 2003/11/25 22:32:45
-i 2003/11/30 18:45:02 EDG fp_conv
-o 2003/11/30 19:45:58
-i 2003/11/30 21:49:24 EDG fp_conv
-o 2003/11/30 22:36:42
-i 2003/12/03 15:48:03 EDG fp_conv
-o 2003/12/03 17:07:22
-i 2003/12/04 14:46:53 EDG fp_conv
-o 2003/12/04 16:05:17
-i 2003/12/07 16:00:38 ForumJobs Meeting
-o 2003/12/07 19:00:27
-i 2003/12/08 00:41:29 EDG fp_conv
-o 2003/12/08 01:18:18
-i 2003/12/08 14:12:19 EDG fp_conv
-o 2003/12/08 14:57:03
-i 2003/12/08 16:14:25 EDG fp_conv
-o 2003/12/08 17:37:53
-i 2003/12/08 22:11:16 EDG fp_conv
-o 2003/12/09 02:18:03
-i 2003/12/09 16:19:26 ForumJobs
-o 2003/12/09 18:41:55
-i 2003/12/09 19:46:55 ForumJobs
-o 2003/12/09 20:12:32
-i 2003/12/09 21:25:34 ForumJobs
-o 2003/12/09 23:23:50
-i 2003/12/09 23:48:46 EDG fp_conv
-o 2003/12/10 03:17:33
-i 2003/12/10 13:50:03 EDG fp_conv
-o 2003/12/10 14:30:31
-i 2003/12/10 16:50:40 EDG fp_conv
-o 2003/12/11 05:12:28
-i 2003/12/11 14:31:30 EDG fp_conv
-o 2003/12/11 18:17:08
-i 2003/12/12 00:56:19 EDG fp_conv
-o 2003/12/12 02:38:32
-i 2003/12/12 16:42:33 EDG fp_conv
-o 2003/12/12 20:13:46
-i 2003/12/12 22:09:46 EDG fp_conv
-o 2003/12/13 01:26:52
-i 2003/12/14 16:00:43 ForumJobs Meeting
-o 2003/12/14 18:44:38
-i 2003/12/14 20:12:59 EDG fp_conv
-o 2003/12/15 02:49:53
-i 2003/12/15 15:21:19 EDG fp_conv
-o 2003/12/15 17:59:45
-i 2003/12/15 19:06:10 EDG fp_conv
-o 2003/12/16 00:12:14
-i 2003/12/16 00:12:15 ForumJobs
-o 2003/12/16 01:16:51
-i 2003/12/16 16:43:32 EDG fp_conv
-o 2003/12/16 18:44:46
-i 2003/12/16 19:54:15 EDG fp_conv
-o 2003/12/17 01:08:19
-i 2003/12/17 01:34:12 ForumJobs
-o 2003/12/17 01:51:34
-i 2003/12/17 16:56:39 EDG fp_conv
-o 2003/12/17 19:15:58
-i 2003/12/17 22:49:59 EDG fp_conv
-o 2003/12/18 00:47:10
-i 2003/12/18 16:53:31 ForumJobs
-o 2003/12/18 18:35:43
-i 2003/12/19 18:12:39 ForumJobs
-o 2003/12/19 20:01:01
-i 2003/12/23 17:30:29 ForumJobs
-o 2003/12/23 18:10:41
-i 2004/01/13 12:32:55 ForumJobs
-o 2004/01/13 12:53:55
-i 2004/01/14 14:23:47 EDG fp_conv
-o 2004/01/14 19:25:42
-i 2004/01/15 17:20:01 EDG fp_conv
-o 2004/01/15 18:40:34
-i 2004/01/16 12:50:26 EDG fp_conv
-o 2004/01/16 18:39:45
-i 2004/01/16 19:23:09 EDG fp_conv
-o 2004/01/16 20:41:14
-i 2004/01/19 12:48:57 EDG fp_conv
-o 2004/01/19 15:18:38
-i 2004/01/20 16:07:50 ForumJobs
-o 2004/01/20 19:18:04
-i 2004/01/21 13:18:04 EDG fp_conv
-o 2004/01/21 18:18:04
-i 2004/01/22 13:39:27 EDG fp_conv
-o 2004/01/22 18:31:03
-i 2004/01/22 19:12:42 EDG fp_conv
-o 2004/01/22 20:48:41
-i 2004/01/23 12:58:41 EDG fp_conv
-o 2004/01/23 15:27:58
-i 2004/01/23 16:00:00 ForumJobs
-o 2004/01/23 19:15:00
-i 2004/01/23 21:30:26 EDG fp_conv
-o 2004/01/23 23:45:56
-i 2004/01/25 17:19:42 ForumJobs
-o 2004/01/25 18:22:37
-i 2004/01/26 22:34:31 ForumJobs
-o 2004/01/26 23:35:23
-i 2004/01/27 12:53:42 EDG fp_conv
-o 2004/01/27 13:23:15
-i 2004/01/27 19:42:50 EDG fp_conv
-o 2004/01/27 19:57:28
-i 2004/01/27 22:08:53 ForumJobs
-o 2004/01/27 22:44:40
-i 2004/01/27 23:14:41 EDG fp_conv
-o 2004/01/27 23:48:05
-i 2004/01/28 00:00:27 ForumJobs
-o 2004/01/28 00:39:21
-i 2004/01/28 17:04:22 ForumJobs
-o 2004/01/28 17:34:31
-i 2004/01/29 14:07:44 ForumJobs
-o 2004/01/29 16:07:04
-i 2004/01/29 17:15:58 ForumJobs
-o 2004/01/29 18:55:40
-i 2004/01/29 22:11:41 ForumJobs
-o 2004/01/29 23:31:41
-i 2004/01/30 15:56:02 ForumJobs
-o 2004/01/30 17:54:06
-i 2004/01/30 20:43:00 ForumJobs
-o 2004/01/30 21:56:30
-i 2004/01/30 22:16:09 ForumJobs
-o 2004/01/30 22:28:35
-i 2004/02/03 17:19:26 ForumJobs
-o 2004/02/03 19:24:08
-i 2004/02/08 14:42:44 ForumJobs
-o 2004/02/08 18:07:07
-i 2004/02/10 18:05:54 EDG fp_conv
-o 2004/02/10 19:10:24
-i 2004/02/10 19:10:25 ForumJobs
-o 2004/02/10 19:16:23
-i 2004/02/11 18:04:55 ForumJobs
-o 2004/02/11 19:25:12
-i 2004/02/11 21:42:52 ForumJobs
-o 2004/02/12 01:16:28
-i 2004/02/12 16:01:50 ForumJobs
-o 2004/02/12 16:45:17
-i 2004/02/17 15:36:11 ForumJobs
-o 2004/02/17 17:37:50
-i 2004/02/17 22:20:06 ForumJobs
-o 2004/02/17 23:20:18
-i 2004/02/20 18:00:44 EDG fp_conv
-o 2004/02/20 19:21:42
-i 2004/02/23 21:16:24 EDG fp_conv
-o 2004/02/24 00:01:01
-i 2004/02/24 21:29:21 EDG fp_conv
-o 2004/02/24 21:53:23
-i 2004/02/25 10:55:19 EDG fp_conv
-o 2004/02/25 13:30:24
-i 2004/02/27 13:57:39 EDG fp_conv
-o 2004/02/27 15:49:31
-i 2004/02/27 16:18:22 EDG fp_conv
-o 2004/02/27 17:47:34
-i 2004/03/02 11:45:36 ForumJobs
-o 2004/03/02 12:45:38
-i 2004/03/02 12:45:38 EDG fp_conv
-o 2004/03/02 18:01:03
-i 2004/03/02 21:03:44 ForumJobs
-o 2004/03/02 21:39:25
-i 2004/03/03 12:05:24 EDG fp_conv
-o 2004/03/03 17:47:43
-i 2004/03/03 20:34:26 EDG fp_conv
-o 2004/03/03 22:04:50
-i 2004/03/04 19:38:23 EDG fp_conv
-o 2004/03/04 21:08:57
-i 2004/03/07 16:53:41 ForumJobs
-o 2004/03/07 17:45:30
-i 2004/03/09 14:24:33 ForumJobs
-o 2004/03/09 15:07:53
-i 2004/03/09 15:07:55 EDG fp_conv
-o 2004/03/09 17:53:35
-i 2004/03/22 23:21:08 ForumJobs
-o 2004/03/23 00:09:32
-i 2004/03/23 15:45:28 ForumJobs
-o 2004/03/23 16:38:24
-i 2004/03/30 23:30:17 ForumJobs
-o 2004/03/31 01:31:43
-i 2004/04/02 17:49:46 ForumJobs
-o 2004/04/02 21:02:43
-i 2004/04/03 20:33:51 ForumJobs
-o 2004/04/03 22:49:54
-i 2004/04/04 18:46:00 ForumJobs
-o 2004/04/04 19:03:09
-i 2004/04/05 20:21:23 ForumJobs
-o 2004/04/05 20:51:24
-i 2004/04/06 15:32:37 ForumJobs
-o 2004/04/06 16:40:53
-i 2004/04/08 12:54:44 ForumJobs
-o 2004/04/08 13:27:18
-i 2004/04/08 14:50:39 ForumJobs
-o 2004/04/08 15:39:51
-i 2004/04/08 16:05:52 ForumJobs
-o 2004/04/08 17:16:33
-i 2004/04/08 23:46:34 ForumJobs
-o 2004/04/09 00:57:38
-i 2004/04/10 13:00:57 ForumJobs
-o 2004/04/10 14:53:01
-i 2004/04/12 16:18:02 ForumJobs
-o 2004/04/12 17:34:57
-i 2004/04/12 23:39:20 ForumJobs
-o 2004/04/13 00:32:45
-i 2004/04/14 12:23:48 ForumJobs
-o 2004/04/14 12:50:42
-i 2004/04/15 16:48:51 ForumJobs
-o 2004/04/15 17:55:10 invoice #1
-i 2004/04/26 12:34:11 ForumJobs
-o 2004/04/26 13:04:54
-i 2004/05/06 14:00:28 ForumJobs
-o 2004/05/06 14:38:53
-i 2004/07/27 14:11:31 Borland
-o 2004/07/27 14:35:56 discussed fake symbol consolidation schemes
-i 2004/07/29 17:54:42 Borland
-o 2004/07/29 18:32:50 discussed hashing issues in fake ns sym lookup
-i 2004/07/30 12:41:33 Borland
-o 2004/07/30 12:57:16 answered namespace lookup questions
-i 2005/04/04 13:03:18 3dex oss
-o 2005/04/04 14:33:18
-i 2005/04/18 11:03:18 3dex oss
-o 2005/04/18 12:36:18
-i 2005/04/18 14:03:18 3dex oss
-o 2005/04/18 16:57:56
-i 2005/05/10 13:45:16 EDG dr
-o 2005/05/10 15:30:52 10 issues checked
-i 2005/05/12 14:32:16 EDG dr
-o 2005/05/12 18:12:55
-i 2005/05/13 11:20:51 EDG dr
-o 2005/05/13 12:41:03
-i 2005/05/13 15:50:54 EDG dr
-o 2005/05/13 16:13:23 break
-i 2005/05/13 16:43:59 EDG dr
-o 2005/05/13 17:37:44
-i 2005/05/16 12:30:37 EDG dr
-o 2005/05/16 13:02:55
-i 2005/05/16 16:02:11 EDG dr
-o 2005/05/16 16:36:20
-i 2005/05/17 18:33:14 EDG dr
-o 2005/05/17 18:51:02
-i 2005/05/18 14:32:08 EDG dr
-o 2005/05/18 15:07:43
-i 2005/05/20 20:02:55 EDG dr
-o 2005/05/20 21:21:14
-i 2005/05/20 21:42:16 EDG dr
-o 2005/05/20 21:52:59
-i 2005/05/21 15:39:59 EDG dr
-o 2005/05/21 16:33:27
-i 2005/05/23 20:48:20 EDG dr
-o 2005/05/23 22:17:08
-i 2005/05/24 13:08:29 EDG dr
-o 2005/05/24 15:25:06
-i 2005/06/28 15:08:29 3dex security
-o 2005/06/28 18:44:13
-i 2005/06/28 22:38:57 3dex ledger
-o 2005/06/28 23:51:31
-i 2005/06/29 16:11:41 3dex ledger
-o 2005/06/29 19:46:04
-i 2005/07/01 15:03:35 3dex ledger
-o 2005/07/01 20:41:08
-i 2005/07/02 14:00:35 3dex ledger
-o 2005/07/02 18:00:35
-i 2005/07/03 13:30:35 3dex ledger
-o 2005/07/03 17:00:35
-i 2005/07/04 14:30:35 3dex ledger
-o 2005/07/04 19:00:35
-i 2005/07/04 20:44:35 3dex ledger
-o 2005/07/04 22:01:35
-i 2005/07/05 17:20:29 3dex ledger
-o 2005/07/05 22:58:35
-i 2005/07/06 23:43:14 3dex ledger
-o 2005/07/07 03:09:01
-i 2005/07/07 19:43:14 3dex ledger
-o 2005/07/07 21:09:01
-i 2005/07/09 13:55:22 3dex ledger
-o 2005/07/09 14:34:29
-i 2005/07/09 15:08:05 3dex ledger
-o 2005/07/09 17:46:15
-i 2005/07/12 21:24:03 3dex ledger
-o 2005/07/13 02:00:03
-i 2005/07/14 21:24:03 3dex ledger
-o 2005/07/14 21:59:40
-i 2005/07/16 22:03:57 3dex ledger
-o 2005/07/17 00:34:07
-i 2005/07/17 10:53:38 3dex ledger
-o 2005/07/17 11:56:49
-i 2005/08/10 15:45:54 3dex soap
-o 2005/08/10 16:12:02
-i 2005/08/11 15:04:23 3dex soap
-o 2005/08/11 16:07:35
-i 2005/08/15 15:07:18 3dex soap
-o 2005/08/15 15:35:18
-i 2005/08/15 15:36:14 3dex soap
-o 2005/08/15 16:18:41
-i 2005/08/17 16:21:10 3dex soap
-o 2005/08/17 16:53:37
-i 2005/08/18 14:01:46 3dex soap
-o 2005/08/18 18:33:12
-i 2005/08/25 13:30:44 3dex soap
-o 2005/08/25 15:38:09
-i 2005/08/25 16:52:18 3dex soap
-o 2005/08/25 17:54:52
-i 2005/08/25 20:19:34 3dex soap
-o 2005/08/25 21:32:07
-i 2005/08/28 18:06:40 3dex soap
-o 2005/08/28 18:36:55
-i 2005/08/28 19:34:56 3dex soap
-o 2005/08/28 19:55:25
-i 2005/10/22 00:55:10 3dex video
-o 2005/10/22 01:52:58
-i 2005/10/22 22:00:59 3dex video
-o 2005/10/22 22:58:30
-i 2005/10/25 13:00:00 MOW meeting
-o 2005/10/25 17:00:00
-i 2005/10/26 10:00:00 MOW meeting
-o 2005/10/26 14:00:00
-i 2005/10/26 18:51:52 MOW planning
-o 2005/10/26 18:57:43
-i 2005/10/27 20:34:28 MOW website
-o 2005/10/27 21:40:28
-i 2005/10/28 22:04:28 MOW website
-o 2005/10/28 22:50:28
-i 2005/10/29 23:04:28 MOW planning
-o 2005/10/29 23:40:28
-i 2005/10/30 22:18:28 MOW website
-o 2005/10/31 01:22:28
-i 2005/10/31 05:15:29 3dex video
-o 2005/10/31 05:55:34
-i 2005/10/31 15:51:55 3dex video
-o 2005/10/31 17:37:09
-i 2005/11/01 01:15:34 MOW website
-o 2005/11/01 02:34:55
-i 2005/11/01 18:04:47 MOW website
-o 2005/11/01 18:35:25
-i 2005/11/01 20:39:42 MOW website
-o 2005/11/01 23:00:08
-i 2005/11/02 00:26:09 MOW website
-o 2005/11/02 04:14:33
-i 2005/11/02 17:07:40 MOW website
-o 2005/11/02 18:13:49
-i 2005/11/02 22:09:53 MOW website
-o 2005/11/02 22:41:31
-i 2005/11/03 00:11:02 MOW website
-o 2005/11/03 04:52:25
-i 2005/11/03 04:55:38 3dex video
-o 2005/11/03 06:22:42
-i 2005/11/03 19:45:00 MOW website
-o 2005/11/03 22:53:12
-i 2005/11/04 00:16:33 MOW website
-o 2005/11/04 00:43:07
-i 2005/11/04 02:01:23 MOW website
-o 2005/11/04 04:31:25
-i 2005/11/04 14:11:55 MOW website
-o 2005/11/04 16:48:30
-i 2005/11/04 16:59:06 MOW website
-o 2005/11/04 19:54:46
-i 2005/11/05 22:29:03 MOW website
-o 2005/11/06 04:53:57
-i 2005/11/07 02:13:36 MOW website
-o 2005/11/07 04:38:12
-i 2005/11/07 20:29:07 MOW website
-o 2005/11/07 23:03:45
-i 2005/11/07 23:53:46 MOW website
-o 2005/11/08 04:35:27
-i 2005/11/08 16:02:23 MOW website
-o 2005/11/08 17:26:28
-i 2005/11/09 00:25:44 MOW website
-o 2005/11/09 03:35:00
-i 2005/11/09 14:28:03 MOW website
-o 2005/11/09 14:49:27
-i 2005/11/09 17:13:19 MOW website
-o 2005/11/09 17:29:51
-i 2005/11/10 00:13:33 MOW website
-o 2005/11/10 03:08:40
-i 2005/11/10 15:22:12 MOW website
-o 2005/11/10 16:33:16
-i 2005/11/10 19:10:44 MOW website
-o 2005/11/10 22:19:44
-i 2005/11/11 01:00:54 MOW website
-o 2005/11/11 01:31:39
-i 2005/11/11 01:50:07 MOW website
-o 2005/11/11 03:13:36
-i 2005/11/11 03:35:18 MOW website
-o 2005/11/11 05:32:27
-i 2005/11/13 20:07:14 MOW website
-o 2005/11/13 21:14:05
-i 2005/11/13 22:02:04 MOW website
-o 2005/11/14 01:34:44
-i 2005/11/14 23:35:33 MOW website
-o 2005/11/15 12:25:00
-i 2005/11/15 01:31:53 MOW website
-o 2005/11/15 01:54:55
-i 2005/11/15 16:58:26 MOW website
-o 2005/11/15 18:17:43
-i 2005/11/15 21:16:00 MOW website
-o 2005/11/15 22:57:24
-i 2005/11/15 23:52:00 MOW website
-o 2005/11/16 07:08:14
-i 2005/11/16 20:06:33 MOW website
-o 2005/11/16 23:00:45
-i 2005/11/17 00:15:29 MOW website
-o 2005/11/17 09:39:11
-i 2005/11/17 15:33:03 MOW website: Polishing MainIndex.aspx
-o 2005/11/17 17:12:52
-i 2005/11/17 20:40:53 MOW website: Fixing the display of StoryTable.ascx
-o 2005/11/18 00:14:58
-i 2005/11/18 00:15:19 MOW website: Improve Asset class
-o 2005/11/18 03:42:35
-i 2005/11/19 19:04:00 MOW website: Fix MainIndex page
-o 2005/11/19 22:30:14
-i 2005/11/19 22:56:38 MOW website: Finalize HTML for AuthorIndex and Profile
-o 2005/11/20 07:49:00
-i 2005/11/20 19:02:48 MOW website: Resolving final issues
-o 2005/11/20 23:58:01
-i 2005/11/22 00:04:47 MOW website: MainIndex - Change header display and fixed alignment
-o 2005/11/22 02:54:14
-i 2005/11/22 02:54:14 MOW website: AuthorProfile - Fix alignment issues created by MainIndex fixes
-o 2005/11/22 03:08:13
-i 2005/11/22 03:08:13 MOW website: Breadcrumb navigation
-o 2005/11/22 04:13:01
-i 2005/11/22 04:13:01 MOW website: CreateTheme - Fixing style
-o 2005/11/22 04:45:41
-i 2005/11/22 04:45:41 MOW website: Confirming deletion
-o 2005/11/22 05:14:26
-i 2005/11/22 05:14:29 MOW website: Yellow message boxes
-o 2005/11/22 06:17:15
-i 2005/11/22 06:47:00 MOW website: MainIndex - Testing and fixing HTML
-o 2005/11/22 08:20:19
-i 2005/11/22 17:41:19 MOW website: MainIndex - Use PostedDate in Themes for sorting
-o 2005/11/22 18:14:23
-i 2005/11/22 18:49:32 MOW website: MainIndex - Use PostedDate in Themes for sorting
-o 2005/11/22 20:01:52
-i 2005/11/23 00:04:07 MOW website: AssetList - Finishing uploads
-o 2005/11/23 01:13:28
-i 2005/11/24 16:49:19 MOW website: AssetList - Support ordering
-o 2005/11/24 20:20:23
-i 2005/11/24 20:50:28 MOW website: AssetList - Finishing uploads
-o 2005/11/24 22:13:13
-i 2005/11/27 19:33:05 MOW website: StoryDetails - Adding other tables
-o 2005/11/27 21:15:26
-i 2005/11/28 20:27:07 MOW website: StoryDetails - Adding other tables
-o 2005/11/28 21:17:52
-i 2005/11/28 21:58:54 MOW website: StoryDetails - Adding other tables
-o 2005/11/29 00:49:57
-i 2005/11/29 02:16:10 MOW website: Use field validators again
-o 2005/11/29 03:20:58
-i 2005/11/29 04:09:57 MOW website: Use field validators again
-o 2005/11/29 04:35:41
-i 2005/11/30 00:08:28 MOW website: AddedStories - The main added story list
-o 2005/11/30 01:00:32
-i 2005/11/30 20:58:15 MOW website: AddedStories - The main added story list
-o 2005/11/30 22:01:42
-i 2005/11/30 22:57:15 MOW website: AddedStories - The main added story list
-o 2005/12/01 03:02:46
-i 2005/12/01 20:32:47 MOW website: AddedStories - The main added story list
-o 2005/12/01 21:18:13
-i 2005/12/01 21:18:27 MOW website: MainIndex - Further corrections using latest HTML
-o 2005/12/01 21:55:20
-i 2005/12/01 22:55:49 MOW website: MainIndex - Further corrections using latest HTML
-o 2005/12/02 03:21:50
-i 2005/12/02 12:19:06 MOW website: BookDescription
-o 2005/12/02 13:27:17
-i 2005/12/02 13:27:22 MOW website: Cleanup
-o 2005/12/02 17:35:32
-i 2005/12/05 17:50:37 MOW website: Cleanup
-o 2005/12/05 17:52:33
-i 2005/12/05 18:44:48 MOW website: Cleanup
-o 2005/12/05 22:13:06
-i 2005/12/05 22:29:40 MOW website: Cleanup
-o 2005/12/06 01:00:03
-i 2005/12/06 01:38:51 MOW website: Cleanup
-o 2005/12/06 02:30:04
-i 2005/12/06 18:44:24 MOW website: Cleanup
-o 2005/12/06 20:00:21
-i 2005/12/06 21:00:03 MOW website: Cleanup
-o 2005/12/07 00:44:28
-i 2005/12/07 00:44:46 MOW website: AuthorProfile - Support for CommLanguage and Passwords
-o 2005/12/07 02:10:41
-i 2005/12/07 02:11:11 MOW website: ShowImage - Make Popup size based on Image size
-o 2005/12/07 02:35:37
-i 2005/12/07 02:41:14 MOW website: ShowImage - Make Popup size based on Image size
-o 2005/12/07 03:02:45
-i 2005/12/07 04:22:17 MOW website: ShowImage - Make Popup size based on Image size
-o 2005/12/07 06:00:31
-i 2005/12/07 06:00:45 MOW website: AuthorIndex - Fixes for the Cleanup
-o 2005/12/07 06:31:09
-i 2005/12/07 10:10:21 MOW website: AddedStories - Add support for searching by author
-o 2005/12/07 11:37:51
-i 2005/12/07 12:55:55 MOW planning
-o 2005/12/07 13:26:03
-i 2005/12/07 13:26:19 MOW website: Cleanup
-o 2005/12/07 14:20:32
-i 2005/12/07 15:13:21 MOW website: Cleanup
-o 2005/12/07 15:46:54
-i 2005/12/07 17:52:33 MOW website: Cleanup
-o 2005/12/07 18:36:52
-i 2005/12/08 10:31:32 MOW website: Cleanup
-o 2005/12/08 16:28:12
-i 2005/12/08 20:37:50 MOW website: Cleanup
-o 2005/12/08 22:38:42
-i 2005/12/09 13:44:36 MOW website: StoryDetails - Split into multiple pages
-o 2005/12/09 14:09:44
-i 2005/12/11 14:46:31 MOW website: StoryDetails - Split into multiple pages
-o 2005/12/11 16:09:49
-i 2005/12/12 11:27:15 MOW website: StoryDetails - Split into multiple pages
-o 2005/12/12 14:39:05
-i 2005/12/12 14:58:15 MOW website: StoryDetails - Split into multiple pages
-o 2005/12/12 17:06:12
-i 2005/12/12 17:06:19 MOW website: Advertisements
-o 2005/12/12 18:22:28
-i 2005/12/12 19:07:13 MOW website: Advertisements
-o 2005/12/12 21:47:22
-i 2005/12/13 17:05:38 MOW website: Events
-o 2005/12/13 17:54:49
-i 2005/12/13 19:08:43 MOW website: Events
-o 2005/12/13 21:43:52
-i 2005/12/14 15:35:08 MOW website: Events
-o 2005/12/14 16:30:54
-i 2005/12/15 13:01:22 MOW website: Events
-o 2005/12/15 14:41:30
-i 2005/12/15 17:25:51 MOW website: Events
-o 2005/12/15 18:07:43
-i 2005/12/16 08:19:13 MOW website: Events
-o 2005/12/16 10:51:19
-i 2005/12/19 14:32:21 MOW website: Bugs
-o 2005/12/19 18:17:29
-i 2005/12/19 19:52:21 MOW website: Events
-o 2005/12/19 22:01:36
-i 2005/12/21 18:52:02 MOW website: TakeAction
-o 2005/12/21 21:30:58
-i 2005/12/29 22:35:56 MOW website: TakeAction
-o 2005/12/29 23:26:52
-i 2005/12/30 22:51:30 MOW website: Flags
-o 2005/12/31 00:02:40
-i 2006/01/02 19:12:34 MOW website: Communication
-o 2006/01/02 19:58:53
-i 2006/01/05 17:53:58 MOW website: Schedule
-o 2006/01/05 18:30:02
-i 2006/01/06 00:08:19 MOW website: Cleanup
-o 2006/01/06 01:36:11
-i 2006/01/07 17:25:54 MOW website: Cleanup
-o 2006/01/07 19:30:29
-i 2006/01/07 22:05:33 MOW website: Cleanup
-o 2006/01/08 00:45:18
-i 2006/01/08 15:36:25 MOW website: Cleanup
-o 2006/01/08 16:41:19
-i 2006/01/08 18:04:57 MOW website: Cleanup
-o 2006/01/08 20:03:15
-i 2006/01/08 20:50:43 MOW website: Cleanup
-o 2006/01/08 22:12:04
-i 2006/01/08 22:12:09 sina
-o 2006/01/08 23:19:16
-i 2006/01/08 23:19:17 MOW website: Cleanup
-o 2006/01/09 01:01:51
-i 2006/01/09 14:46:53 MOW website: Cleanup
-o 2006/01/09 17:19:53
-i 2006/01/09 18:19:54 MOW website: Cleanup
-o 2006/01/09 19:35:47
-i 2006/01/12 14:50:26 MOW website: Cleanup
-o 2006/01/12 17:34:41
-i 2006/01/12 19:59:47 MOW website: Cleanup
-o 2006/01/12 23:33:20
-i 2006/01/13 15:32:37 MOW website: Cleanup
-o 2006/01/13 16:03:19
-i 2006/01/14 18:50:12 sina
-o 2006/01/14 19:22:54
-i 2006/01/15 01:14:21 sina
-o 2006/01/15 01:50:04
-i 2006/01/15 02:21:13 MOW website: PressReleases
-o 2006/01/15 03:11:35
-i 2006/01/16 02:25:45 sina
-o 2006/01/16 02:59:01
-i 2006/01/16 18:08:28 MOW planning
-o 2006/01/16 18:21:21
-i 2006/01/16 21:43:57 sina
-o 2006/01/16 22:57:09
-i 2006/01/17 00:23:05 sina
-o 2006/01/17 02:51:55
-i 2006/01/17 18:01:54 sina
-o 2006/01/17 18:22:33
-i 2006/01/17 19:00:48 sina
-o 2006/01/17 19:19:36
-i 2006/01/17 19:34:10 sina
-o 2006/01/17 19:50:48
-i 2006/01/17 19:53:38 MOW website: v11
-o 2006/01/17 21:09:27
-i 2006/01/17 21:33:29 sina
-o 2006/01/17 21:55:42
-i 2006/01/17 22:02:38 sina
-o 2006/01/17 22:28:36
-i 2006/01/17 22:28:59 MOW website: v11
-o 2006/01/17 22:48:06
-i 2006/01/18 01:57:59 MOW website: v11
-o 2006/01/18 03:27:34
-i 2006/01/18 03:50:52 sina
-o 2006/01/18 04:32:47
-i 2006/01/18 18:07:31 MOW website: TakeAction
-o 2006/01/18 21:01:43
-i 2006/01/18 23:53:49 MOW website: TakeAction
-o 2006/01/19 01:20:50
-i 2006/01/19 14:50:56 MOW website: TakeAction
-o 2006/01/19 15:40:04
-i 2006/01/19 17:53:04 MOW website: TakeAction
-o 2006/01/19 19:25:36
-i 2006/01/22 00:59:17 MOW website: Cleanup
-o 2006/01/22 01:23:58
-i 2006/01/22 07:43:01 MOW website: Cleanup
-o 2006/01/22 10:02:30
-i 2006/01/22 19:18:23 MOW website: Cleanup
-o 2006/01/22 19:48:01
-i 2006/01/22 20:31:36 MOW website: Cleanup
-o 2006/01/22 23:05:58
-i 2006/01/23 18:45:59 MOW website: SubTheme
-o 2006/01/23 19:50:39
-i 2006/01/23 21:05:19 MOW website: SubTheme
-o 2006/01/24 01:02:44
-i 2006/01/24 20:07:33 MOW website: Bugs
-o 2006/01/24 20:39:11
-i 2006/01/25 08:38:02 MOW website: Bugs
-o 2006/01/25 10:17:25
-i 2006/01/25 11:54:50 MOW website: Bugs
-o 2006/01/25 14:26:52
-i 2006/01/27 03:42:03 MOW website: Bugs
-o 2006/01/27 04:35:28
-i 2006/01/27 05:25:53 MOW website: Bugs
-o 2006/01/27 06:14:55
-i 2006/01/27 16:27:55 MOW website: Bugs
-o 2006/01/27 16:36:42
-i 2006/01/27 17:08:46 MOW website: Bugs
-o 2006/01/27 17:38:40
-i 2006/01/29 15:42:37 MOW website: Bugs
-o 2006/01/29 16:12:01
-i 2006/01/29 22:12:15 MOW website: Bugs
-o 2006/01/30 00:30:12
-i 2006/01/30 13:24:14 MOW website: Comments
-o 2006/01/30 14:54:21
-i 2006/01/30 15:38:38 MOW website: Events
-o 2006/01/30 18:30:18
-i 2006/01/30 18:50:55 MOW website: AboutTheBook
-o 2006/01/30 19:14:55
-i 2006/01/31 12:30:40 MOW website: AboutTheBook
-o 2006/01/31 14:20:46
-i 2006/01/31 16:11:25 MOW website: Events
-o 2006/01/31 18:35:55
-i 2006/02/01 03:44:57 MOW website: public
-o 2006/02/01 04:21:29
-i 2006/02/01 10:40:37 MOW website: public
-o 2006/02/01 15:19:13
-i 2006/02/01 16:49:14 MOW website: public
-o 2006/02/01 19:37:46
-i 2006/02/02 09:55:16 MOW website: public
-o 2006/02/02 10:34:26
-i 2006/02/02 15:47:38 MOW website: public
-o 2006/02/02 18:39:48
-i 2006/02/03 09:14:47 MOW website: public
-o 2006/02/03 10:21:18
-i 2006/02/03 16:21:20 MOW website: public
-o 2006/02/03 17:26:02
-i 2006/02/05 11:49:52 MOW website: public
-o 2006/02/05 22:49:53
-i 2006/02/06 16:49:23 MOW website: public
-o 2006/02/06 18:10:33
-i 2006/02/07 17:01:45 MOW website: public
-o 2006/02/07 18:39:24
-i 2006/02/07 21:00:15 sina
-o 2006/02/08 23:27:28
-i 2006/02/08 11:47:31 MOW website: public
-o 2006/02/08 12:09:20
-i 2006/02/08 12:21:06 MOW website: public
-o 2006/02/08 12:54:37
-i 2006/02/10 21:20:03 MOW website: public
-o 2006/02/10 23:36:40
-i 2006/02/16 21:26:56 3dex scheduler
-o 2006/02/16 22:52:50
-i 2006/02/16 23:35:24 3dex scheduler
-o 2006/02/17 01:11:31
-i 2006/02/17 17:57:19 MOW website: public
-o 2006/02/17 19:09:45
-i 2006/02/17 21:00:15 sina
-o 2006/02/17 21:30:15
-i 2006/02/18 22:00:57 3dex scheduler
-o 2006/02/18 22:59:26
-i 2006/02/19 01:14:16 3dex scheduler
-o 2006/02/19 02:32:59
-i 2006/02/19 17:05:01 3dex scheduler
-o 2006/02/19 17:26:51
-i 2006/02/20 22:28:05 3dex scheduler
-o 2006/02/20 22:48:37
-i 2006/02/21 14:50:37 MOW website: Events
-o 2006/02/21 16:55:24
-i 2006/02/21 17:14:06 MOW website: Events
-o 2006/02/21 18:20:14
-i 2006/02/21 19:34:15 MOW website: Events
-o 2006/02/21 20:00:09
-i 2006/02/23 18:02:57 sina
-o 2006/02/23 19:35:47
-i 2006/02/28 16:01:01 MOW website: Factoids
-o 2006/02/28 18:32:39
-i 2006/02/28 22:13:01 MOW website: testing
-o 2006/02/28 23:41:58
-i 2006/03/02 12:52:49 MOW website: Factoids
-o 2006/03/02 14:13:21
-i 2006/03/02 16:01:03 MOW website: bugs
-o 2006/03/02 17:45:58
-i 2006/03/02 18:10:59 MOW website: bugs
-o 2006/03/02 18:59:01
-i 2006/03/03 16:23:29 MOW website: bugs
-o 2006/03/03 17:23:29
-i 2006/03/10 16:45:13 MOW website: testing
-o 2006/03/10 17:25:14
-i 2006/03/11 16:54:29 MOW website: testing
-o 2006/03/11 18:03:01
-i 2006/03/11 21:06:39 MOW website: testing
-o 2006/03/11 21:36:29
-i 2006/03/11 23:59:37 sina
-o 2006/03/12 03:30:39
-i 2006/03/13 00:41:27 MOW website: testing
-o 2006/03/13 02:04:44
-i 2006/03/14 03:19:06 MOW website: testing
-o 2006/03/14 03:37:49
-i 2006/03/15 02:03:32 MOW website: bugs
-o 2006/03/15 04:04:44
-i 2006/03/15 21:02:35 College:Setup
-o 2006/03/15 22:10:44
-i 2006/03/16 01:08:22 College:Setup
-o 2006/03/16 02:28:17
-i 2006/03/16 03:02:34 College:Setup
-o 2006/03/16 03:34:47
-i 2006/03/16 08:08:17 College:Setup
-o 2006/03/16 08:59:51
-i 2006/03/22 10:31:58 sina
-o 2006/03/22 13:06:15
diff --git a/tests/confirm.py b/tests/confirm.py
deleted file mode 100755
index f4947224..00000000
--- a/tests/confirm.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/python
-
-# This script confirms what ledger tells you.
-
-import sys
-import os
-import re
-
-def clean(num):
- return float(re.sub("(\s+|\$|,)","", num))
-
-running_total = 0.0
-index = 1
-last_line = ""
-errors = 0
-
-report = sys.argv[1]
-for line in os.popen("./ledger -f utils/standard.dat -e 2004/4 %s reg %s" %
- (report, sys.argv[2])):
- match = re.match("\\s*([-$,0-9.]+)\\s+([-$,0-9.]+)", line[55:])
- if not match:
- continue
- value = clean(match.group(1))
- total = clean(match.group(2))
-
- running_total += value
- diff = abs(running_total - total)
- if report == "-V" or report == "-G" and diff < 0.015:
- diff = 0.0
- if diff > 0.001:
- print "! discrepancy of %.2f (%.2f - %.2f) at line %d:" % \
- (running_total - total, running_total, total, index)
- print line,
- running_total = total
- errors += 1
-
- index += 1
- last_line = line
-
-balance_total = 0.0
-
-for line in os.popen("./ledger -f utils/standard.dat -e 2004/4 %s bal %s" %
- (report, sys.argv[2])):
- if line[0] != '-':
- balance_total = clean(line[:20])
-
-diff = abs(balance_total - running_total)
-if report == "-V" or report == "-G" and diff < 0.015:
- diff = 0.0
-if diff > 0.001:
- print
- print "! discrepancy of %.2f (%.2f - %.2f) between register and balance" % \
- (balance_total - running_total, balance_total, running_total)
- print last_line,
- print line,
- errors += 1
-
-sys.exit(errors)
diff --git a/tests/parser.h b/tests/parser.h
deleted file mode 100644
index aa1a3a74..00000000
--- a/tests/parser.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef __TESTFILEFORMAT_H
-#define __TESTFILEFORMAT_H
-
-#include <cxxtest/TestSuite.h>
-
-#include <ledger.h>
-
-using namespace std;
-using namespace ledger;
-
-class TestFileFormat : public CxxTest::TestSuite
-{
-public:
- void testEmptyFileIsTextualFile()
- {
- stringstream emptyStream(stringstream::in);
- textual_parser_t textualParser;
- TS_ASSERT(textualParser.test(emptyStream));
- TS_ASSERT(emptyStream.good());
- TS_ASSERT_EQUALS(0, emptyStream.tellg());
- }
-
- void testEmptyFileIsNotXMLFile()
- {
-#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
- stringstream emptyStream(stringstream::in);
- xml_parser_t xmlParser;
- TS_ASSERT(!xmlParser.test(emptyStream));
- TS_ASSERT(emptyStream.good());
- TS_ASSERT_EQUALS(0, emptyStream.tellg());
-#endif
- }
-
- void testEmptyFileIsNotGnuCashFile()
- {
-#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
- stringstream emptyStream(stringstream::in);
- gnucash_parser_t gnucashParser;
- TS_ASSERT(!gnucashParser.test(emptyStream));
- TS_ASSERT(emptyStream.good());
- TS_ASSERT_EQUALS(0, emptyStream.tellg());
-#endif
- }
-
- void testEmptyFileIsNotBinaryFile()
- {
- stringstream emptyStream(stringstream::in);
- binary_parser_t binaryParser;
- TS_ASSERT(!binaryParser.test(emptyStream));
- TS_ASSERT(emptyStream.good());
- TS_ASSERT_EQUALS(0, emptyStream.tellg());
- }
-
- void testEmptyFileIsNotQIFFile()
- {
- stringstream emptyStream(stringstream::in);
- qif_parser_t qifParser;
- TS_ASSERT(!qifParser.test(emptyStream));
- TS_ASSERT(emptyStream.good());
- TS_ASSERT_EQUALS(0, emptyStream.tellg());
- }
-
-};
-
-#endif // __TESTFILEFORMAT_H
diff --git a/tests/regress b/tests/regress
deleted file mode 100755
index 9a6c4412..00000000
--- a/tests/regress
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/bin/sh
-
-TMPDIR=/tmp
-TESTS=tests
-UTILS=utils
-CASES=$TESTS/cases
-
-result=0
-
-generate=false
-if [ "$1" = "--generate" ]; then
- generate=true
-fi
-
-runtest() {
- num=$1
- shift
- if [ $generate = true ]; then
- echo generating $num
- ./ledger "$@" > $TESTS/baseline/$num 2> $TMPDIR/errors-$$.out
- cat $TMPDIR/errors-$$.out >> $TESTS/baseline/$num
- rm -f $TMPDIR/*-$$.out
- elif [ -r $TESTS/baseline/$num ]; then
- ./ledger "$@" > $TMPDIR/test-$$.out 2> $TMPDIR/errors-$$.out
- cat $TMPDIR/errors-$$.out >> $TMPDIR/test-$$.out
-
- diff $TESTS/baseline/$num $TMPDIR/test-$$.out \
- > $TMPDIR/result-$$.out 2>&1
- if [ -s $TMPDIR/result-$$.out ]; then
- echo Error: Regression $num failed
- echo ":: regression $num: ./ledger $@" >> errors.out
- cat $TMPDIR/result-$$.out >> errors.out
- result=`expr $result + 1`
- fi
- rm -f $TMPDIR/*-$$.out
- fi
-}
-
-echo Running Ledger regression tests...
-
-runtest 1032 -f $CASES/1032.dat -S t bal
-
-runtest 1031 -f $CASES/1030.dat reg
-runtest 1030 -f $CASES/1030.dat bal
-
-runtest 1029 -f $CASES/1002.dat entry 2006/10/20 "stock option"
-runtest 1028 -f $CASES/1002.dat entry 2006/10/20 "stock option" -20
-runtest 1027 -f $CASES/1002.dat entry 2006/10/20 "stock option" opti
-runtest 1026 -f $CASES/1002.dat entry 2006/10/20 "stock option" time
-runtest 1025 -f $CASES/1002.dat entry 2006/10/20 "stock option" gain
-runtest 1024 -f $CASES/1002.dat entry 2006/10/20 "stock option" opti -20
-runtest 1023 -f $CASES/1002.dat entry 2006/10/20 "stock option" time -20
-runtest 1022 -f $CASES/1002.dat entry 2006/10/20 "stock option" gain -20
-
-runtest 1021 -f $CASES/1002.dat entry 2006/10/20 "stock optionx"
-runtest 1020 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" -20
-runtest 1019 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" opti
-runtest 1018 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" time
-runtest 1017 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" gain
-runtest 1016 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" opti -20
-runtest 1015 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" time -20
-runtest 1014 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" gain -20
-
-runtest 1013 -f $CASES/1002.dat entry 2006/10/20 "stock option" xopti
-runtest 1012 -f $CASES/1002.dat entry 2006/10/20 "stock option" xtime
-runtest 1011 -f $CASES/1002.dat entry 2006/10/20 "stock option" xgain
-runtest 1010 -f $CASES/1002.dat entry 2006/10/20 "stock option" xopti -20
-runtest 1009 -f $CASES/1002.dat entry 2006/10/20 "stock option" xtime -20
-runtest 1008 -f $CASES/1002.dat entry 2006/10/20 "stock option" xgain -20
-
-runtest 1007 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" xopti
-runtest 1006 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" xtime
-runtest 1005 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" xgain
-runtest 1004 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" xopti -20
-runtest 1003 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" xtime -20
-runtest 1002 -f $CASES/1002.dat entry 2006/10/20 "stock optionx" xgain -20
-
-runtest 1001 -f $CASES/1001.dat bal
-
-if [ -f $UTILS/standard.dat ]; then
- runtest 10 -f $UTILS/standard.dat --truncate=trailing -M -r -s -n reg rent
- runtest 9 -f $UTILS/standard.dat --truncate=trailing -M -r -s reg rent
- runtest 8 -f $UTILS/standard.dat --truncate=trailing -M -r -n reg rent
- runtest 7 -f $UTILS/standard.dat --truncate=trailing -M -r reg rent
- runtest 6 -f $UTILS/standard.dat --truncate=trailing -M reg rent
- runtest 5 -f $UTILS/standard.dat --truncate=trailing -r -s -n reg rent
- runtest 4 -f $UTILS/standard.dat --truncate=trailing -r -s reg rent
- runtest 3 -f $UTILS/standard.dat --truncate=trailing -r -n reg rent
- runtest 2 -f $UTILS/standard.dat --truncate=trailing -r reg rent
- runtest 1 -f $UTILS/standard.dat --truncate=trailing reg rent
-fi
-
-echo Running Ledger regression tests...done
-
-exit $result
diff --git a/tests/regtest b/tests/regtest
deleted file mode 100755
index 57dec8e0..00000000
--- a/tests/regtest
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-errors=0
-
-if [ ! -f utils/standard.dat ]; then
- exit 0
-fi
-
-for test in \
- "-O nrl:checking" \
- "-O ^expenses" \
- "-B 401" \
- "-V 401" \
- "-G 401" \
- "-B ira" \
- "-V ira" \
- "-G ira" \
- "-B retire" \
- "-V retire" \
- "-G retire"
-do
- echo testing: $test
- python tests/confirm.py $test
- errors=`expr $errors + $?`
-done
-
-exit $errors
diff --git a/tests/runtests.py b/tests/runtests.py
deleted file mode 100755
index 7649f775..00000000
--- a/tests/runtests.py
+++ /dev/null
@@ -1,184 +0,0 @@
-#!/usr/bin/env python
-
-import random
-import string
-import signal
-import os
-import sys
-import time
-
-true, false = 1, 0
-
-options = [
- "--account=TempAccount",
- "--actual",
- "--add-budget",
- "--amount-data",
- "--amount=a",
- "--ansi",
- "--ansi-invert",
- "--average",
- #"--balance-format",
- "--basis",
- "--begin=2004/01",
- "--budget",
- "--by-payee",
- #"--cache=/tmp/cache",
- "--cleared",
- "--collapse",
- "--comm-as-payee",
- #"--csv-register-format",
- "--current",
- "--date-format=%Y",
- "--descend='$100'",
- "--descend-if='t=={$100}'",
- "--deviation",
- "--display='a>10'",
- "--dow",
- "--download",
- "--effective",
- "--empty",
- "--end=2005/01",
- #"--equity-format",
- #"--file=/tmp/file",
- "--forecast='d<[2006]'",
- "--format=%Y",
- #"--full-help",
- "--gain",
- "--head=10",
- #"--help",
- #"--help-calc",
- #"--help-comm",
- #"--help-disp",
- #"--init-file=/tmp/init",
- #"--input-date-format",
- "--limit='a>10'",
- "--lots",
- "--lot-prices",
- "--lot-dates",
- "--lot-tags",
- "--market",
- "--monthly",
- "--no-cache",
- #"--output=/tmp/output",
- #"--pager",
- #"--percentage",
- "--performance",
- "--period-sort=A\\(t\\)",
- "--period=oct",
- #"--plot-amount-format",
- #"--plot-total-format",
- "--price",
- "--price-exp=1000",
- #"--price-db=/tmp/foo",
- #"--prices-format",
- #"--print-format",
- "--quantity",
- "--real",
- #"--reconcile",
- #"--reconcile-date",
- #"--register-format",
- "--related",
- "--sort=A\\(t\\)",
- "--subtotal",
- "--tail=5",
- "--total-data",
- "--total=O",
- "--totals",
- "--unbudgeted",
- "--uncleared",
- #"--version",
- "--weekly",
- "--wide",
- #"--wide-register-format",
- #"--write-hdr-format",
- #"--write-xact-format",
- "--yearly",
-]
-
-commands = [
- "bal rent",
- "bal ira",
- "bal auto",
- "reg rent",
- "reg ira",
- "reg expenses:food",
- "print rent",
- "print irc",
- "xml rent",
- "xml irc",
- "equity rent",
- "equity ira",
- "prices AAPL",
-]
-
-random.seed ()
-
-loop = true
-count = 0
-errors = 0
-if len(sys.argv) > 1:
- errors = int(sys.argv[1])
-signals = 0
-
-while loop:
- try:
- n = random.randint (0, len (options))
- opts = random.sample (options, n)
- for cmd in commands:
- if os.path.exists ("/tmp/out"):
- os.unlink ("/tmp/out")
-
- cmd = "./ledger -f utils/standard.dat " + string.join(opts, " ") + " " + cmd + \
- " >> /tmp/out 2>&1"
-
- sys.stdout = open ("/tmp/out", "w")
- print "::", cmd
- sys.stdout.close ()
-
- ret = os.system (cmd)
-
- sys.stdout = open ("/tmp/out", "a")
-
- # Convert an odd UNIX return type into the appropriate
- # signal indication.
- if ret and ret % 256 == 0 and ret / 256 > 127:
- ret = 0x100 + (ret / 256 - 128)
-
- if ret and ret % 256 == 0:
- print "ERROR: Return value", ret / 256
- sys.stdout.close ()
- os.system ("cat /tmp/out >> errors.out")
- errors += 1
- elif ret:
- if ret % 256 == signal.SIGINT:
- loop = false
- break
- print "SIGNAL: Return value", ret % 256
- sys.stdout.close ()
- os.system ("cat /tmp/out >> signals.out")
- signals += 1
- else:
- sys.stdout.close ()
- os.system ("cat /tmp/out >> results.out")
-
- sys.stdout = sys.__stdout__
- count += 1
- if count < 10 or \
- (count < 100 and count % 10 == 0) or \
- (count < 1000 and count % 100 == 0) or \
- count % 1000 == 0:
- if signals > 0 and errors > 0:
- print "%d tests ... (%d signals, %d errors)" % \
- (count, signals, errors)
- elif signals > 0:
- print "%d tests ... (%d signals)" % \
- (count, signals)
- elif errors > 0:
- print "%d tests ... (%d errors)" % \
- (count, errors)
- else:
- print "%d tests ..." % count
-
- except KeyboardInterrupt:
- loop = false
diff --git a/tests/textual.h b/tests/textual.h
deleted file mode 100644
index adf24c77..00000000
--- a/tests/textual.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __TESTTEXTUALJOURNAL_H
-#define __TESTTEXTUALJOURNAL_H
-
-#include <cxxtest/TestSuite.h>
-
-#include <textual.h>
-#include <config.h>
-
-using namespace std;
-using namespace ledger;
-
-class TestTextualJournal : public CxxTest::TestSuite
-{
-public:
- void testEmptyFileIsTextualFile()
- {
- stringstream j(stringstream::in);
-
- j << "2005/10/15 Something" << endl;
- j << " A $ 42" << endl;
- j << " B" << endl;
-
- textual_parser_t textualParser;
- TS_ASSERT(textualParser.test(j));
- TS_ASSERT(j.good());
- TS_ASSERT_EQUALS(0, j.tellg());
-
- config_t config;
- std::auto_ptr<journal_t> journal(new journal_t);
- textualParser.parse(j, config, journal.get());
- }
-};
-
-#endif // __TESTTEXTUALJOURNAL_H
diff --git a/textual.cc b/textual.cc
deleted file mode 100644
index 2033106b..00000000
--- a/textual.cc
+++ /dev/null
@@ -1,1045 +0,0 @@
-#if defined(__GNUG__) && __GNUG__ < 3
-#define _XOPEN_SOURCE
-#endif
-
-#include "journal.h"
-#include "textual.h"
-#include "datetime.h"
-#include "valexpr.h"
-#include "error.h"
-#include "option.h"
-#include "config.h"
-#include "timing.h"
-#include "util.h"
-#include "acconf.h"
-
-#include <fstream>
-#include <sstream>
-#include <cstring>
-#include <cctype>
-#include <cstdio>
-#include <cstdlib>
-#include <climits>
-
-#ifdef HAVE_REALPATH
-extern "C" char *realpath(const char *, char resolved_path[]);
-#endif
-
-#define TIMELOG_SUPPORT 1
-
-namespace ledger {
-
-#define MAX_LINE 1024
-
-static std::string path;
-static unsigned int linenum;
-static unsigned int src_idx;
-static accounts_map account_aliases;
-
-static std::list<std::pair<std::string, int> > include_stack;
-
-#ifdef TIMELOG_SUPPORT
-struct time_entry_t {
- datetime_t checkin;
- account_t * account;
- std::string desc;
-
- time_entry_t() : account(NULL) {}
- time_entry_t(datetime_t _checkin,
- account_t * _account = NULL,
- std::string _desc = "")
- : checkin(_checkin), account(_account), desc(_desc) {}
-
- time_entry_t(const time_entry_t& entry)
- : checkin(entry.checkin), account(entry.account),
- desc(entry.desc) {}
-};
-#endif
-
-inline char * next_element(char * buf, bool variable = false)
-{
- for (char * p = buf; *p; p++) {
- if (! (*p == ' ' || *p == '\t'))
- continue;
-
- if (! variable) {
- *p = '\0';
- return skip_ws(p + 1);
- }
- else if (*p == '\t') {
- *p = '\0';
- return skip_ws(p + 1);
- }
- else if (*(p + 1) == ' ') {
- *p = '\0';
- return skip_ws(p + 2);
- }
- }
- return NULL;
-}
-
-static value_expr parse_amount_expr(std::istream& in, amount_t& amount,
- transaction_t * xact,
- unsigned short flags = 0)
-{
- value_expr expr(parse_value_expr(in, NULL, flags | PARSE_VALEXPR_RELAXED |
- PARSE_VALEXPR_PARTIAL)->acquire());
-
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed an amount expression");
-
-#ifdef DEBUG_ENABLED
- DEBUG_IF("ledger.textual.parse") {
- if (_debug_stream) {
- ledger::dump_value_expr(*_debug_stream, expr);
- *_debug_stream << std::endl;
- }
- }
-#endif
-
- if (! compute_amount(expr, amount, xact))
- throw new parse_error("Amount expression failed to compute");
-
-#if 0
- if (expr->kind == value_expr_t::CONSTANT) {
- expr = NULL;
- } else {
- DEBUG_IF("ledger.textual.parse") {
- std::cout << "Value expression tree:" << std::endl;
- ledger::dump_value_expr(std::cout, expr.get());
- }
- }
-#else
- expr = NULL;
-#endif
-
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "The transaction amount is " << xact->amount);
- return expr;
-}
-
-transaction_t * parse_transaction(char * line, account_t * account,
- entry_t * entry = NULL)
-{
- std::istringstream in(line);
-
- std::string err_desc;
- try {
-
- // The account will be determined later...
- std::auto_ptr<transaction_t> xact(new transaction_t(NULL));
- if (entry)
- xact->entry = entry;
-
- // Parse the state flag
-
- char p = peek_next_nonws(in);
- switch (p) {
- case '*':
- xact->state = transaction_t::CLEARED;
- in.get(p);
- p = peek_next_nonws(in);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed the CLEARED flag");
- break;
- case '!':
- xact->state = transaction_t::PENDING;
- in.get(p);
- p = peek_next_nonws(in);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed the PENDING flag");
- break;
- }
-
- // Parse the account name
-
- unsigned long account_beg = in.tellg();
- unsigned long account_end = account_beg;
- while (! in.eof()) {
- in.get(p);
- if (in.eof() || (std::isspace(p) &&
- (p == '\t' || in.peek() == EOF ||
- std::isspace(in.peek()))))
- break;
- account_end++;
- }
-
- if (account_beg == account_end)
- throw new parse_error("No account was specified");
-
- char * b = &line[account_beg];
- char * e = &line[account_end];
- if ((*b == '[' && *(e - 1) == ']') ||
- (*b == '(' && *(e - 1) == ')')) {
- xact->flags |= TRANSACTION_VIRTUAL;
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a virtual account name");
- if (*b == '[') {
- xact->flags |= TRANSACTION_BALANCE;
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a balanced virtual account name");
- }
- b++; e--;
- }
-
- std::string name(b, e - b);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed account name " << name);
- if (account_aliases.size() > 0) {
- accounts_map::const_iterator i = account_aliases.find(name);
- if (i != account_aliases.end())
- xact->account = (*i).second;
- }
- if (! xact->account)
- xact->account = account->find_account(name);
-
- // Parse the optional amount
-
- if (in.good() && ! in.eof()) {
- p = peek_next_nonws(in);
- if (in.eof())
- goto finished;
- if (p == ';')
- goto parse_note;
-
- try {
- unsigned long beg = (long)in.tellg();
-
- xact->amount_expr =
- parse_amount_expr(in, xact->amount, xact.get(),
- PARSE_VALEXPR_NO_REDUCE);
-
- unsigned long end = (long)in.tellg();
- xact->amount_expr.expr = std::string(line, beg, end - beg);
- }
- catch (error * err) {
- err_desc = "While parsing transaction amount:";
- throw err;
- }
- }
-
- // Parse the optional cost (@ PER-UNIT-COST, @@ TOTAL-COST)
-
- if (in.good() && ! in.eof()) {
- p = peek_next_nonws(in);
- if (p == '@') {
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Found a price indicator");
- bool per_unit = true;
- in.get(p);
- if (in.peek() == '@') {
- in.get(p);
- per_unit = false;
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "And it's for a total price");
- }
-
- if (in.good() && ! in.eof()) {
- xact->cost = new amount_t;
-
- try {
- unsigned long beg = (long)in.tellg();
-
- if (parse_amount_expr(in, *xact->cost, xact.get(),
- PARSE_VALEXPR_NO_MIGRATE))
- throw new parse_error
- ("A transaction's cost must evaluate to a constant value");
-
- unsigned long end = (long)in.tellg();
-
- if (per_unit)
- xact->cost_expr = (std::string("@") +
- std::string(line, beg, end - beg));
- else
- xact->cost_expr = (std::string("@@") +
- std::string(line, beg, end - beg));
- }
- catch (error * err) {
- err_desc = "While parsing transaction cost:";
- throw err;
- }
-
- if (*xact->cost < 0)
- throw new parse_error("A transaction's cost may not be negative");
-
- amount_t per_unit_cost(*xact->cost);
- if (per_unit)
- *xact->cost *= xact->amount;
- else
- per_unit_cost /= xact->amount;
-
- if (xact->amount.commodity() &&
- ! xact->amount.commodity().annotated)
- xact->amount.annotate_commodity(per_unit_cost);
-
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Total cost is " << *xact->cost);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Per-unit cost is " << per_unit_cost);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Annotated amount is " << xact->amount);
- }
- }
- }
-
- xact->amount.reduce();
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Reduced amount is " << xact->amount);
-
- // Parse the optional note
-
- parse_note:
- if (in.good() && ! in.eof()) {
- p = peek_next_nonws(in);
- if (p == ';') {
- in.get(p);
- p = peek_next_nonws(in);
- xact->note = &line[in.tellg()];
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a note '" << xact->note << "'");
-
- if (char * b = std::strchr(xact->note.c_str(), '['))
- if (char * e = std::strchr(xact->note.c_str(), ']')) {
- char buf[256];
- std::strncpy(buf, b + 1, e - b - 1);
- buf[e - b - 1] = '\0';
-
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a transaction date " << buf);
-
- try {
- if (char * p = std::strchr(buf, '=')) {
- *p++ = '\0';
- xact->_date_eff = p;
- }
- if (buf[0])
- xact->_date = buf;
- }
- catch (...) {
- // If it fails to parse, just ignore it...
- }
- }
- }
- }
-
- finished:
- return xact.release();
-
- }
- catch (error * err) {
- err->context.push_back
- (new line_context(line, (long)in.tellg() - 1,
- ! err_desc.empty() ?
- err_desc : "While parsing transaction:"));
- throw err;
- }
-}
-
-bool parse_transactions(std::istream& in,
- account_t * account,
- entry_base_t& entry,
- const std::string& kind,
- unsigned long beg_pos)
-{
- static char line[MAX_LINE + 1];
- bool added = false;
-
- while (! in.eof() && (in.peek() == ' ' || in.peek() == '\t')) {
- in.getline(line, MAX_LINE);
- if (in.eof())
- break;
-
- int len = std::strlen(line);
- if (line[len - 1] == '\r')
- line[--len] = '\0';
-
- beg_pos += len + 1;
- linenum++;
-
- if (line[0] == ' ' || line[0] == '\t') {
- char * p = skip_ws(line);
- if (! *p)
- break;
- }
- if (transaction_t * xact = parse_transaction(line, account)) {
- entry.add_transaction(xact);
- added = true;
- }
- }
-
- return added;
-}
-
-namespace {
- TIMER_DEF(parsing_total, "total parsing time");
- TIMER_DEF(entry_xacts, "parsing transactions");
- TIMER_DEF(entry_details, "parsing entry details");
- TIMER_DEF(entry_date, "parsing entry date");
-}
-
-entry_t * parse_entry(std::istream& in, char * line, account_t * master,
- textual_parser_t& parser, unsigned long& pos)
-{
- std::auto_ptr<entry_t> curr(new entry_t);
-
- // Parse the date
-
- TIMER_START(entry_date);
-
- char * next = next_element(line);
-
- if (char * p = std::strchr(line, '=')) {
- *p++ = '\0';
- curr->_date_eff = p;
- }
- curr->_date = line;
-
- TIMER_STOP(entry_date);
-
- // Parse the optional cleared flag: *
-
- TIMER_START(entry_details);
-
- transaction_t::state_t state = transaction_t::UNCLEARED;
- if (next) {
- switch (*next) {
- case '*':
- state = transaction_t::CLEARED;
- next = skip_ws(++next);
- break;
- case '!':
- state = transaction_t::PENDING;
- next = skip_ws(++next);
- break;
- }
- }
-
- // Parse the optional code: (TEXT)
-
- if (next && *next == '(') {
- if (char * p = std::strchr(next++, ')')) {
- *p++ = '\0';
- curr->code = next;
- next = skip_ws(p);
- }
- }
-
- // Parse the description text
-
- curr->payee = next ? next : "<Unspecified payee>";
-
- TIMER_STOP(entry_details);
-
- // Parse all of the transactions associated with this entry
-
- TIMER_START(entry_xacts);
-
- unsigned long end_pos;
- unsigned long beg_line;
-
- while (! in.eof() && (in.peek() == ' ' || in.peek() == '\t')) {
- unsigned long beg_pos = (unsigned long)in.tellg();
-
- line[0] = '\0';
- in.getline(line, MAX_LINE);
- if (in.eof() && line[0] == '\0')
- break;
-
- int len = std::strlen(line);
- if (line[len - 1] == '\r')
- line[--len] = '\0';
-
- end_pos = beg_pos + len + 1;
- beg_line = linenum;
- linenum++;
-
- if (line[0] == ' ' || line[0] == '\t') {
- char * p = skip_ws(line);
- if (! *p)
- break;
- }
-
- if (transaction_t * xact = parse_transaction(line, master, curr.get())) {
- if (state != transaction_t::UNCLEARED &&
- xact->state == transaction_t::UNCLEARED)
- xact->state = state;
-
- xact->beg_pos = beg_pos;
- xact->beg_line = beg_line;
- xact->end_pos = end_pos;
- xact->end_line = linenum;
- pos = end_pos;
-
- curr->add_transaction(xact);
- }
-
- if (in.eof())
- break;
- }
-
- TIMER_STOP(entry_xacts);
-
- return curr.release();
-}
-
-template <typename T>
-struct push_var {
- T& var;
- T prev;
- push_var(T& _var) : var(_var), prev(var) {}
- ~push_var() { var = prev; }
-};
-
-static inline void parse_symbol(char *& p, std::string& symbol)
-{
- if (*p == '"') {
- char * q = std::strchr(p + 1, '"');
- if (! q)
- throw new parse_error("Quoted commodity symbol lacks closing quote");
- symbol = std::string(p + 1, 0, q - p - 1);
- p = q + 2;
- } else {
- char * q = next_element(p);
- symbol = p;
- if (q)
- p = q;
- else
- p += symbol.length();
- }
- if (symbol.empty())
- throw new parse_error("Failed to parse commodity");
-}
-
-bool textual_parser_t::test(std::istream& in) const
-{
- char buf[5];
-
- in.read(buf, 5);
- if (std::strncmp(buf, "<?xml", 5) == 0) {
-#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
- throw new parse_error("Ledger file contains XML data, but format was not recognized");
-#else
- throw new parse_error("Ledger file contains XML data, but no XML support present");
-#endif
- }
-
- in.clear();
- in.seekg(0, std::ios::beg);
- assert(in.good());
- return true;
-}
-
-static void clock_out_from_timelog(std::list<time_entry_t>& time_entries,
- const datetime_t& when,
- account_t * account,
- const char * desc,
- journal_t * journal)
-{
- time_entry_t event;
-
- if (time_entries.size() == 1) {
- event = time_entries.back();
- time_entries.clear();
- }
- else if (time_entries.empty()) {
- throw new parse_error("Timelog check-out event without a check-in");
- }
- else if (! account) {
- throw new parse_error
- ("When multiple check-ins are active, checking out requires an account");
- }
- else {
- bool found = false;
-
- for (std::list<time_entry_t>::iterator i = time_entries.begin();
- i != time_entries.end();
- i++)
- if (account == (*i).account) {
- event = *i;
- found = true;
- time_entries.erase(i);
- break;
- }
-
- if (! found)
- throw new parse_error
- ("Timelog check-out event does not match any current check-ins");
- }
-
- if (desc && event.desc.empty()) {
- event.desc = desc;
- desc = NULL;
- }
-
- std::auto_ptr<entry_t> curr(new entry_t);
- curr->_date = when;
- curr->code = desc ? desc : "";
- curr->payee = event.desc;
-
- if (curr->_date < event.checkin)
- throw new parse_error
- ("Timelog check-out date less than corresponding check-in");
-
- char buf[32];
- std::sprintf(buf, "%lds", curr->_date - event.checkin);
- amount_t amt;
- amt.parse(buf);
-
- transaction_t * xact
- = new transaction_t(event.account, amt, TRANSACTION_VIRTUAL);
- xact->state = transaction_t::CLEARED;
- curr->add_transaction(xact);
-
- if (! journal->add_entry(curr.get()))
- throw new parse_error("Failed to record 'out' timelog entry");
- else
- curr.release();
-}
-
-unsigned int textual_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
-{
- static bool added_auto_entry_hook = false;
- static char line[MAX_LINE + 1];
- char c;
- unsigned int count = 0;
- unsigned int errors = 0;
-
- TIMER_START(parsing_total);
-
- std::list<account_t *> account_stack;
- auto_entry_finalizer_t auto_entry_finalizer(journal);
- std::list<time_entry_t> time_entries;
-
- if (! master)
- master = journal->master;
-
- account_stack.push_front(master);
-
- path = journal->sources.back();
- src_idx = journal->sources.size() - 1;
- linenum = 1;
-
- unsigned long beg_pos = in.tellg();
- unsigned long end_pos;
- unsigned long beg_line;
-
- while (in.good() && ! in.eof()) {
- try {
- in.getline(line, MAX_LINE);
- if (in.eof())
- break;
-
- int len = std::strlen(line);
- if (line[len - 1] == '\r')
- line[--len] = '\0';
-
- end_pos = beg_pos + len + 1;
- beg_line = linenum;
- linenum++;
-
- switch (line[0]) {
- case '\0':
- break;
-
- case ' ':
- case '\t': {
- char * p = skip_ws(line);
- if (*p)
- throw new parse_error("Line begins with whitespace");
- break;
- }
-
-#ifdef TIMELOG_SUPPORT
- case 'i':
- case 'I': {
- std::string date(line, 2, 19);
-
- char * p = skip_ws(line + 22);
- char * n = next_element(p, true);
-
- time_entry_t event(date, account_stack.front()->find_account(p),
- n ? n : "");
-
- if (! time_entries.empty())
- for (std::list<time_entry_t>::iterator i = time_entries.begin();
- i != time_entries.end();
- i++)
- if (event.account == (*i).account)
- throw new parse_error
- ("Cannot double check-in to the same account");
-
- time_entries.push_back(event);
- break;
- }
-
- case 'o':
- case 'O':
- if (time_entries.empty()) {
- throw new parse_error("Timelog check-out event without a check-in");
- } else {
- std::string date(line, 2, 19);
-
- char * p = skip_ws(line + 22);
- char * n = next_element(p, true);
-
- clock_out_from_timelog
- (time_entries, date,
- p ? account_stack.front()->find_account(p) : NULL, n, journal);
- count++;
- }
- break;
-#endif // TIMELOG_SUPPORT
-
- case 'D': { // a default commodity for "entry"
- amount_t amt(skip_ws(line + 1));
- commodity_t::default_commodity = &amt.commodity();
- break;
- }
-
- case 'A': // a default account for unbalanced xacts
- journal->basket =
- account_stack.front()->find_account(skip_ws(line + 1));
- break;
-
- case 'C': // a set of conversions
- if (char * p = std::strchr(line + 1, '=')) {
- *p++ = '\0';
- parse_conversion(line + 1, p);
- }
- break;
-
- case 'P': { // a pricing entry
- char * date_field_ptr = skip_ws(line + 1);
- char * time_field_ptr = next_element(date_field_ptr);
- if (! time_field_ptr) break;
- std::string date_field = date_field_ptr;
-
- char * symbol_and_price;
- datetime_t datetime;
-
- if (std::isdigit(time_field_ptr[0])) {
- symbol_and_price = next_element(time_field_ptr);
- if (! symbol_and_price) break;
- datetime = date_field + " " + time_field_ptr;
- } else {
- symbol_and_price = time_field_ptr;
- datetime = date_t(date_field);
- }
-
- std::string symbol;
- parse_symbol(symbol_and_price, symbol);
- amount_t price;
- price.parse(symbol_and_price, AMOUNT_PARSE_NO_MIGRATE);
-
- if (commodity_t * commodity = commodity_t::find_or_create(symbol))
- commodity->add_price(datetime, price);
- break;
- }
-
- case 'N': { // don't download prices
- char * p = skip_ws(line + 1);
- std::string symbol;
- parse_symbol(p, symbol);
-
- if (commodity_t * commodity = commodity_t::find_or_create(symbol))
- commodity->add_flags(COMMODITY_STYLE_NOMARKET);
- break;
- }
-
- case 'Y': // set the current year
- date_t::current_year = std::atoi(skip_ws(line + 1));
- break;
-
-#ifdef TIMELOG_SUPPORT
- case 'h':
- case 'b':
-#endif
- case '*': // comment line
- case ';': // comment line
- break;
-
- case '-': { // option setting
- char * p = next_element(line);
- if (! p) {
- p = std::strchr(line, '=');
- if (p)
- *p++ = '\0';
- }
- process_option(config_options, line + 2, p);
- break;
- }
-
- case '=': { // automated entry
- if (! added_auto_entry_hook) {
- journal->add_entry_finalizer(&auto_entry_finalizer);
- added_auto_entry_hook = true;
- }
-
- auto_entry_t * ae = new auto_entry_t(skip_ws(line + 1));
- if (parse_transactions(in, account_stack.front(), *ae,
- "automated", end_pos)) {
- journal->auto_entries.push_back(ae);
- ae->src_idx = src_idx;
- ae->beg_pos = beg_pos;
- ae->beg_line = beg_line;
- ae->end_pos = end_pos;
- ae->end_line = linenum;
- }
- break;
- }
-
- case '~': { // period entry
- period_entry_t * pe = new period_entry_t(skip_ws(line + 1));
- if (! pe->period)
- throw new parse_error(std::string("Parsing time period '") + line + "'");
-
- if (parse_transactions(in, account_stack.front(), *pe,
- "period", end_pos)) {
- if (pe->finalize()) {
- extend_entry_base(journal, *pe, true);
- journal->period_entries.push_back(pe);
- pe->src_idx = src_idx;
- pe->beg_pos = beg_pos;
- pe->beg_line = beg_line;
- pe->end_pos = end_pos;
- pe->end_line = linenum;
- } else {
- throw new parse_error("Period entry failed to balance");
- }
- }
- break;
- }
-
- case '@':
- case '!': { // directive
- char * p = next_element(line);
- std::string word(line + 1);
- if (word == "include") {
- push_var<std::string> save_path(path);
- push_var<unsigned int> save_src_idx(src_idx);
- push_var<unsigned long> save_beg_pos(beg_pos);
- push_var<unsigned long> save_end_pos(end_pos);
- push_var<unsigned int> save_linenum(linenum);
-
- path = p;
- if (path[0] != '/' && path[0] != '\\' && path[0] != '~') {
- std::string::size_type pos = save_path.prev.rfind('/');
- if (pos == std::string::npos)
- pos = save_path.prev.rfind('\\');
- if (pos != std::string::npos)
- path = std::string(save_path.prev, 0, pos + 1) + path;
- }
- path = resolve_path(path);
-
- DEBUG_PRINT("ledger.textual.include", "line " << linenum << ": " <<
- "Including path '" << path << "'");
-
- include_stack.push_back(std::pair<std::string, int>
- (journal->sources.back(), linenum - 1));
- count += parse_journal_file(path, config, journal,
- account_stack.front());
- include_stack.pop_back();
- }
- else if (word == "account") {
- account_t * acct;
- acct = account_stack.front()->find_account(p);
- account_stack.push_front(acct);
- }
- else if (word == "end") {
- account_stack.pop_front();
- }
- else if (word == "alias") {
- char * b = p;
- if (char * e = std::strchr(b, '=')) {
- char * z = e - 1;
- while (std::isspace(*z))
- *z-- = '\0';
- *e++ = '\0';
- e = skip_ws(e);
-
- // Once we have an alias name (b) and the target account
- // name (e), add a reference to the account in the
- // `account_aliases' map, which is used by the transaction
- // parser to resolve alias references.
- account_t * acct = account_stack.front()->find_account(e);
- std::pair<accounts_map::iterator, bool> result
- = account_aliases.insert(accounts_pair(b, acct));
- assert(result.second);
- }
- }
- else if (word == "def") {
- if (! global_scope.get())
- init_value_expr();
- parse_value_definition(p);
- }
- break;
- }
-
- default: {
- unsigned long pos = beg_pos;
- if (entry_t * entry =
- parse_entry(in, line, account_stack.front(), *this, pos)) {
- if (journal->add_entry(entry)) {
- entry->src_idx = src_idx;
- entry->beg_pos = beg_pos;
- entry->beg_line = beg_line;
- entry->end_pos = pos;
- entry->end_line = linenum;
- count++;
- } else {
- delete entry;
- throw new parse_error("Entry does not balance");
- }
- } else {
- throw new parse_error("Failed to parse entry");
- }
- end_pos = pos;
- break;
- }
- }
- }
- catch (error * err) {
- for (std::list<std::pair<std::string, int> >::reverse_iterator i =
- include_stack.rbegin();
- i != include_stack.rend();
- i++)
- err->context.push_back(new include_context((*i).first, (*i).second,
- "In file included from"));
- err->context.push_front(new file_context(path, linenum - 1));
-
- std::cout.flush();
- if (errors > 0 && err->context.size() > 1)
- std::cerr << std::endl;
- err->reveal_context(std::cerr, "Error");
- std::cerr << err->what() << std::endl;
- delete err;
- errors++;
- }
- beg_pos = end_pos;
- }
-
- done:
- if (! time_entries.empty()) {
- std::list<account_t *> accounts;
-
- for (std::list<time_entry_t>::iterator i = time_entries.begin();
- i != time_entries.end();
- i++)
- accounts.push_back((*i).account);
-
- for (std::list<account_t *>::iterator i = accounts.begin();
- i != accounts.end();
- i++)
- clock_out_from_timelog(time_entries, datetime_t::now, *i, NULL, journal);
-
- assert(time_entries.empty());
- }
-
- if (added_auto_entry_hook)
- journal->remove_entry_finalizer(&auto_entry_finalizer);
-
- if (errors > 0)
- throw (int)errors;
-
- TIMER_STOP(parsing_total);
-
- return count;
-}
-
-void write_textual_journal(journal_t& journal, std::string path,
- item_handler<transaction_t>& formatter,
- const std::string& write_hdr_format,
- std::ostream& out)
-{
- unsigned long index = 0;
- std::string found;
-
- if (path.empty()) {
- if (! journal.sources.empty())
- found = *journal.sources.begin();
- } else {
-#ifdef HAVE_REALPATH
- char buf1[PATH_MAX];
- char buf2[PATH_MAX];
-
- ::realpath(path.c_str(), buf1);
-
- for (strings_list::iterator i = journal.sources.begin();
- i != journal.sources.end();
- i++) {
- ::realpath((*i).c_str(), buf2);
- if (std::strcmp(buf1, buf2) == 0) {
- found = *i;
- break;
- }
- index++;
- }
-#else
- for (strings_list::iterator i = journal.sources.begin();
- i != journal.sources.end();
- i++) {
- if (path == *i) {
- found = *i;
- break;
- }
- index++;
- }
-#endif
- }
-
- if (found.empty())
- throw new error(std::string("Journal does not refer to file '") +
- path + "'");
-
- entries_list::iterator el = journal.entries.begin();
- auto_entries_list::iterator al = journal.auto_entries.begin();
- period_entries_list::iterator pl = journal.period_entries.begin();
-
- unsigned long pos = 0;
-
- format_t hdr_fmt(write_hdr_format);
- std::ifstream in(found.c_str());
-
- while (! in.eof()) {
- entry_base_t * base = NULL;
- if (el != journal.entries.end() && pos == (*el)->beg_pos) {
- hdr_fmt.format(out, details_t(**el));
- base = *el++;
- }
- else if (al != journal.auto_entries.end() && pos == (*al)->beg_pos) {
- out << "= " << (*al)->predicate_string << '\n';
- base = *al++;
- }
- else if (pl != journal.period_entries.end() && pos == (*pl)->beg_pos) {
- out << "~ " << (*pl)->period_string << '\n';
- base = *pl++;
- }
-
- char c;
- if (base) {
- for (transactions_list::iterator x = base->transactions.begin();
- x != base->transactions.end();
- x++)
- if (! ((*x)->flags & TRANSACTION_AUTO)) {
- transaction_xdata(**x).dflags |= TRANSACTION_TO_DISPLAY;
- formatter(**x);
- }
- formatter.flush();
-
- while (pos < base->end_pos) {
- in.get(c);
- pos = in.tellg(); // pos++;
- }
- } else {
- in.get(c);
- pos = in.tellg(); // pos++;
- out.put(c);
- }
- }
-}
-
-} // namespace ledger
diff --git a/textual.h b/textual.h
deleted file mode 100644
index 8ad653c5..00000000
--- a/textual.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef _TEXTUAL_H
-#define _TEXTUAL_H
-
-#include "parser.h"
-#include "format.h"
-#include "walk.h"
-
-namespace ledger {
-
-class textual_parser_t : public parser_t
-{
- public:
- virtual bool test(std::istream& in) const;
-
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
-};
-
-transaction_t * parse_transaction_text(char * line, account_t * account);
-transaction_t * parse_transaction(std::istream& in, account_t * account);
-
-void write_textual_journal(journal_t& journal, std::string path,
- item_handler<transaction_t>& formatter,
- const std::string& write_hdr_format,
- std::ostream& out);
-
-class include_context : public file_context {
- public:
- include_context(const std::string& file, unsigned long line,
- const std::string& desc = "") throw()
- : file_context(file, line, desc) {}
- virtual ~include_context() throw() {}
-
- virtual void describe(std::ostream& out) const throw() {
- if (! desc.empty())
- out << desc << ": ";
- out << "\"" << file << "\", line " << line << ":" << std::endl;
- }
-};
-
-} // namespace ledger
-
-#endif // _TEXTUAL_H
diff --git a/timing.h b/timing.h
deleted file mode 100644
index 7e1029ea..00000000
--- a/timing.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef _TIMING_H
-#define _TIMING_H
-
-#include "debug.h"
-
-#include <ctime>
-
-namespace ledger {
-
-class timing_t
-{
- public:
- std::clock_t begin;
- std::clock_t cumulative;
- std::string file;
- unsigned long line;
- std::string symbol;
- std::string category;
-
- timing_t(const std::string& _symbol, const std::string& _category)
- : begin(0), cumulative(0), symbol(_symbol), category(_category) {}
-
- timing_t(const std::string& _symbol)
- : begin(0), cumulative(0), symbol(_symbol) {}
-
- ~timing_t() {
- std::string cls = "timing.results.";
- cls += symbol;
- DEBUG_PRINT(cls.c_str(), file << ":" << line << ": "
- << category << " = "
- << (double(cumulative) / double(CLOCKS_PER_SEC)) << "s");
- }
-
- void start(const std::string& _file, unsigned long _line) {
- file = _file;
- line = _line;
- begin = std::clock();
- }
- void start() {
- begin = std::clock();
- }
-
- void stop() {
- cumulative += std::clock() - begin;
- }
-};
-
-#ifdef DEBUG_ENABLED
-#define TIMER_DEF(sym, cat) static timing_t sym(#sym, cat)
-#define TIMER_DEF_(sym) static timing_t sym(#sym, #sym)
-#define TIMER_START(sym) sym.start(__FILE__, __LINE__)
-#define TIMER_STOP(sym) sym.stop()
-#else
-#define TIMER_DEF(sym, cat)
-#define TIMER_DEF_(sym)
-#define TIMER_START(sym)
-#define TIMER_STOP(sym)
-#endif
-
-} // namespace ledger
-
-#endif // _TIMING_H
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 00000000..09daafe6
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,527 @@
+VERSION = 3.0.0
+ACLOCAL_AMFLAGS = -I m4
+dist_man_MANS = doc/ledger.1
+SUBDIRS = po intl
+EXTRA_DIST = autogen.sh config.rpath contrib src/system.hh.in
+DISTCLEANFILES = .timestamp
+
+lib_LTLIBRARIES = \
+ libledger_report.la \
+ libledger_data.la \
+ libledger_expr.la \
+ libledger_math.la \
+ libledger_util.la
+
+lib_cppflags = -I$(srcdir)/src -I$(srcdir)/lib \
+ -I$(srcdir)/lib/utfcpp/source
+
+libledger_util_la_SOURCES = \
+ src/stream.cc \
+ src/mask.cc \
+ src/times.cc \
+ src/error.cc \
+ src/utils.cc \
+ src/accum.cc \
+ lib/sha1.cpp
+
+libledger_util_la_CPPFLAGS = $(lib_cppflags)
+libledger_util_la_LDFLAGS = -release $(VERSION)
+
+libledger_math_la_SOURCES = \
+ src/value.cc \
+ src/balance.cc \
+ src/quotes.cc \
+ src/pool.cc \
+ src/annotate.cc \
+ src/commodity.cc \
+ src/amount.cc
+
+libledger_math_la_CPPFLAGS = $(lib_cppflags)
+libledger_math_la_LDFLAGS = -release $(VERSION)
+
+libledger_expr_la_SOURCES = \
+ src/option.cc \
+ src/format.cc \
+ src/query.cc \
+ src/predicate.cc \
+ src/scope.cc \
+ src/interactive.cc \
+ src/expr.cc \
+ src/op.cc \
+ src/parser.cc \
+ src/token.cc
+
+libledger_expr_la_CPPFLAGS = $(lib_cppflags)
+libledger_expr_la_LDFLAGS = -release $(VERSION)
+
+libledger_data_la_SOURCES = \
+ src/compare.cc \
+ src/iterators.cc \
+ src/timelog.cc \
+ src/textual.cc \
+ src/journal.cc \
+ src/archive.cc \
+ src/account.cc \
+ src/xact.cc \
+ src/post.cc \
+ src/item.cc
+
+libledger_data_la_CPPFLAGS = $(lib_cppflags)
+libledger_data_la_LDFLAGS = -release $(VERSION)
+
+libledger_report_la_SOURCES = \
+ src/stats.cc \
+ src/generate.cc \
+ src/draft.cc \
+ src/emacs.cc \
+ src/xml.cc \
+ src/output.cc \
+ src/precmd.cc \
+ src/chain.cc \
+ src/filters.cc \
+ src/temps.cc \
+ src/report.cc \
+ src/session.cc
+
+libledger_report_la_CPPFLAGS = $(lib_cppflags)
+libledger_report_la_LDFLAGS = -release $(VERSION)
+
+pkginclude_HEADERS = \
+ src/utils.h \
+ src/flags.h \
+ src/error.h \
+ src/times.h \
+ src/mask.h \
+ src/stream.h \
+ src/pstream.h \
+ src/unistring.h \
+ src/accum.h \
+ \
+ src/amount.h \
+ src/commodity.h \
+ src/annotate.h \
+ src/pool.h \
+ src/quotes.h \
+ src/balance.h \
+ src/value.h \
+ \
+ src/token.h \
+ src/parser.h \
+ src/op.h \
+ src/exprbase.h \
+ src/expr.h \
+ src/scope.h \
+ src/interactive.h \
+ src/predicate.h \
+ src/query.h \
+ src/format.h \
+ src/option.h \
+ \
+ src/item.h \
+ src/post.h \
+ src/xact.h \
+ src/account.h \
+ src/journal.h \
+ src/archive.h \
+ src/timelog.h \
+ src/iterators.h \
+ src/compare.h \
+ \
+ src/session.h \
+ src/report.h \
+ src/filters.h \
+ src/temps.h \
+ src/chain.h \
+ src/precmd.h \
+ src/draft.h \
+ src/generate.h \
+ src/stats.h \
+ src/output.h \
+ src/xml.h \
+ src/emacs.h \
+ \
+ src/global.h \
+ \
+ src/pyinterp.h \
+ \
+ lib/sha1.h \
+ lib/gettext.h \
+ \
+ lib/utfcpp/source/utf8.h \
+ lib/utfcpp/source/utf8/checked.h \
+ lib/utfcpp/source/utf8/core.h \
+ lib/utfcpp/source/utf8/unchecked.h
+
+nodist_libledger_util_la_SOURCES = system.hh
+
+BUILT_SOURCES = system.hh
+CLEANFILES = system.hh
+
+system.hh: src/system.hh.in
+ cp -p $< $@
+
+if USE_PCH
+nodist_libledger_util_la_SOURCES += system.hh.gch
+
+BUILT_SOURCES += system.hh.gch
+CLEANFILES += system.hh.gch
+
+system.hh.gch: system.hh
+ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(lib_cppflags) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
+ -o $@ $<
+endif
+
+######################################################################
+
+bin_PROGRAMS = ledger
+
+ledger_CPPFLAGS = $(lib_cppflags)
+if HAVE_BOOST_PYTHON
+ledger_CPPFLAGS += -I$(srcdir)/python
+endif
+ledger_SOURCES = src/main.cc src/global.cc
+ledger_LDADD = $(LIBOBJS) $(lib_LTLIBRARIES) $(INTLLIBS)
+ledger_LDFLAGS = -static
+
+info_TEXINFOS = doc/ledger.texi
+
+dist_lisp_LISP = lisp/ledger.el lisp/timeclock.el
+ELCFILES =
+DISTCLEANFILES += ledger.elc timeclock.elc
+
+all_sources = $(libledger_util_la_SOURCES) \
+ $(libledger_math_la_SOURCES) \
+ $(libledger_expr_la_SOURCES) \
+ $(libledger_data_la_SOURCES) \
+ $(libledger_report_la_SOURCES) \
+ $(libledger_python_la_SOURCES) \
+ src/pyledger.cc
+
+all_files = $(all_sources) $(pkginclude_HEADERS)
+
+######################################################################
+
+if HAVE_BOOST_PYTHON
+
+lib_LTLIBRARIES += libledger_python.la
+
+libledger_python_la_SOURCES = \
+ src/pyutils.h \
+ src/pyfstream.h \
+ src/py_account.cc \
+ src/py_amount.cc \
+ src/py_balance.cc \
+ src/py_commodity.cc \
+ src/py_expr.cc \
+ src/py_format.cc \
+ src/py_item.cc \
+ src/py_journal.cc \
+ src/py_post.cc \
+ src/py_times.cc \
+ src/py_utils.cc \
+ src/py_value.cc \
+ src/py_xact.cc \
+ src/pyinterp.cc
+
+libledger_python_la_CPPFLAGS = $(lib_cppflags) -I$(srcdir)/python
+
+pyexec_LTLIBRARIES = ledger.la
+
+ledger_la_CPPFLAGS = $(libledger_python_la_CPPFLAGS)
+ledger_la_SOURCES = src/pyledger.cc
+ledger_la_DEPENDENCIES = $(lib_LTLIBRARIES)
+ledger_la_LDFLAGS = -avoid-version -module
+ledger_la_LIBADD = $(LIBOBJS) $(lib_LTLIBRARIES)
+
+pkgpython_PYTHON = python/__init__.py python/server.py
+
+endif
+
+######################################################################
+
+TESTS =
+
+if HAVE_PYTHON
+TESTS += RegressTests BaselineTests ManualTests ConfirmTests GenerateTests
+endif
+
+if HAVE_CPPUNIT
+TESTS += \
+ UtilTests \
+ MathTests \
+ ExprTests \
+ DataTests \
+ ReportTests
+endif
+
+if HAVE_BOOST_PYTHON
+TESTS += PyUnitTests
+endif
+
+check_PROGRAMS = $(TESTS)
+
+UtilTests_SOURCES = \
+ test/UnitTests.cc \
+ test/UnitTests.h \
+ test/UtilTests.cc \
+ test/unit/t_utils.cc \
+ test/unit/t_utils.h \
+ test/unit/t_times.cc \
+ test/unit/t_times.h
+
+UtilTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
+UtilTests_LDADD = libledger_util.la -lcppunit
+
+MathTests_SOURCES = \
+ test/UnitTests.cc \
+ test/UnitTests.h \
+ test/MathTests.cc \
+ test/unit/t_commodity.cc \
+ test/unit/t_commodity.h \
+ test/unit/t_amount.cc \
+ test/unit/t_amount.h \
+ test/unit/t_balance.cc \
+ test/unit/t_balance.h
+
+MathTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
+MathTests_LDADD = libledger_math.la $(UtilTests_LDADD)
+
+ExprTests_SOURCES = \
+ test/UnitTests.cc \
+ test/UnitTests.h \
+ test/ExprTests.cc \
+ test/unit/t_expr.cc \
+ test/unit/t_expr.h
+
+ExprTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
+ExprTests_LDADD = libledger_expr.la $(MathTests_LDADD)
+
+DataTests_SOURCES = \
+ test/UnitTests.cc \
+ test/UnitTests.h \
+ test/DataTests.cc
+
+DataTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
+DataTests_LDADD = libledger_data.la $(ExprTests_LDADD)
+
+ReportTests_SOURCES = \
+ test/UnitTests.cc \
+ test/UnitTests.h \
+ test/ReportTests.cc
+
+ReportTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
+ReportTests_LDADD = libledger_report.la $(DataTests_LDADD)
+
+all_tests_sources = \
+ $(UtilTests_SOURCES) \
+ $(MathTests_SOURCES) \
+ $(ExprTests_SOURCES) \
+ $(DataTests_SOURCES) \
+ $(ReportTests_SOURCES)
+
+PyUnitTests_SOURCES = test/PyUnitTests.py
+
+all_py_tests_sources = \
+ $(patsubst test/unit/%.cc,$(top_builddir)/test/python/%.py, \
+ $(filter test/unit/t_%.cc,$(all_tests_sources)))
+
+test/python/%.py: test/unit/%.cc test/convert.py
+ $(PYTHON) $(srcdir)/test/convert.py $< $@
+
+test/python/UnitTests.py: $(all_py_tests_sources)
+ @echo "from unittest import TextTestRunner, TestSuite" > $@
+ @for file in $$(ls $(srcdir)/test/unit/*.cc); do \
+ base=$$(basename $$file); \
+ base=$$(echo $$base | sed 's/\.cc//'); \
+ echo "import $$base" >> $@; \
+ done
+ @echo "suites = [" >> $@
+ @for file in $$(ls $(srcdir)/test/unit/*.cc); do \
+ base=$$(basename $$file); \
+ base=$$(echo $$base | sed 's/\.cc//'); \
+ echo " $$base.suite()," >> $@; \
+ done
+ @echo "]" >> $@
+ @echo "TextTestRunner().run(TestSuite(suites))" >> $@
+
+ledger_python = $(top_builddir)/ledger$(EXEEXT) python
+
+ESC_python=`echo "$(ledger_python)" | sed 's/\//\\\\\//g'`
+ESC_srcdir=`echo "$(srcdir)" | sed 's/\//\\\\\//g'`
+ESC_builddir=`echo "$(top_builddir)" | sed 's/\//\\\\\//g'`
+ESC_distdir=`echo "$(distdir)" | sed 's/\//\\\\\//g'`
+
+# jww (2007-05-10): This rule will not be triggered on systems that
+# define an EXEEXT.
+PyUnitTests: test/PyUnitTests.py test/python/UnitTests.py
+ @cat $(srcdir)/test/PyUnitTests.py \
+ | sed "s/%python%/$(ESC_python)/" \
+ | sed "s/%srcdir%/$(ESC_srcdir)/g" \
+ | sed "s/%builddir%/$(ESC_builddir)/g" > $@
+ chmod 755 $@
+
+RegressTests_SOURCES = test/RegressTests.py
+
+EXTRA_DIST += test/regress test/convert.py test/LedgerHarness.py
+
+RegressTests: $(srcdir)/test/RegressTests.py
+ echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/regress \"\$$@\"" > $@
+ chmod 755 $@
+
+BaselineTests_SOURCES = test/RegressTests.py
+
+EXTRA_DIST += test/baseline
+
+BaselineTests: $(srcdir)/test/RegressTests.py
+ echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/baseline \"\$$@\"" > $@
+ chmod 755 $@
+
+ManualTests_SOURCES = test/RegressTests.py
+
+EXTRA_DIST += test/manual
+
+ManualTests: $(srcdir)/test/RegressTests.py
+ echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/manual \"\$$@\"" > $@
+ chmod 755 $@
+
+ConfirmTests_SOURCES = test/ConfirmTests.py
+
+EXTRA_DIST += test/input
+
+test/input/mondo.dat: test/input/standard.dat
+ @for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do \
+ for j in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do \
+ cat $< >> $@; \
+ done; \
+ done
+
+ConfirmTests: $(srcdir)/test/ConfirmTests.py
+ echo "$(PYTHON) $(srcdir)/test/ConfirmTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/input \"\$$@\"" > $@
+ chmod 755 $@
+
+GenerateTests_SOURCES = test/GenerateTests.py
+
+GenerateTests: $(srcdir)/test/GenerateTests.py
+ echo "$(PYTHON) $(srcdir)/test/GenerateTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) 1 20 \"\$$@\"" > $@
+ chmod 755 $@
+
+FULLCHECK=$(srcdir)/test/fullcheck.sh
+
+if HAVE_CPPUNIT
+cppunittests: check
+ @sh $(FULLCHECK) $(top_builddir)/UtilTests$(EXEEXT) --verify \
+ 2>&1 | grep -v '^GuardMalloc:'
+ @sh $(FULLCHECK) $(top_builddir)/MathTests$(EXEEXT) --verify \
+ 2>&1 | grep -v '^GuardMalloc:'
+ @sh $(FULLCHECK) $(top_builddir)/ExprTests$(EXEEXT) --verify \
+ 2>&1 | grep -v '^GuardMalloc:'
+ @sh $(FULLCHECK) $(top_builddir)/DataTests$(EXEEXT) --verify \
+ 2>&1 | grep -v '^GuardMalloc:'
+ @sh $(FULLCHECK) $(top_builddir)/ReportTests$(EXEEXT) --verify \
+ 2>&1 | grep -v '^GuardMalloc:'
+else
+cppunittests: check
+ @test 1 -eq 1
+endif
+
+fullcheck: cppunittests
+ @$(top_builddir)/RegressTests --verify
+ @$(top_builddir)/BaselineTests --verify
+ @$(top_builddir)/ManualTests --verify
+ @$(top_builddir)/ConfirmTests --verify
+ @$(top_builddir)/GenerateTests --verify
+ @$(top_builddir)/RegressTests --gmalloc
+ @$(top_builddir)/BaselineTests --gmalloc
+ @$(top_builddir)/ManualTests --gmalloc
+# @$(top_builddir)/ConfirmTests --gmalloc
+# @$(top_builddir)/GenerateTests --gmalloc
+
+######################################################################
+
+EXTRA_DIST += doc/README doc/NEWS doc/ledger.pdf
+EXTRA_DIST += doc/LICENSE doc/LICENSE-sha1 doc/LICENSE-utfcpp
+if USE_DOXYGEN
+EXTRA_DIST += doc/Doxyfile doc/refman.pdf
+endif
+
+DISTCLEANFILES += doc/ledger.info doc/ledger.pdf
+if USE_DOXYGEN
+DISTCLEANFILES += Doxyfile.gen doc/Doxyfile.bak doc/refman.pdf
+endif
+
+if USE_DOXYGEN
+dist-hook-doxygen:
+ find $(distdir)/doc -name .dirstamp -delete
+ rm -fr $(distdir)/doc/latex \
+ $(distdir)/doc/Doxyfile.bak \
+ $(distdir)/doc/Doxyfile.gen
+ cp -pR doc/html $(distdir)/doc
+else
+dist-hook-doxygen:
+ @test 1 -eq 1
+endif
+
+dist-hook: dist-hook-doxygen
+ find $(distdir) -name .DS_Store -delete
+ find $(distdir) -name .localized -delete
+ rm -f $(distdir)/README.textile
+ cp -p $(srcdir)/doc/README $(distdir)/README
+
+if USE_DOXYGEN
+distclean-local-doxygen:
+ rm -fr doc/html doc/latex
+ rm -f doc/refman.pdf
+else
+distclean-local-doxygen:
+ @test 1 -eq 1
+endif
+
+distclean-local: distclean-local-doxygen
+ rm -fr test/python
+
+if USE_DOXYGEN
+ESC_top_builddir=`cd $(top_builddir); pwd | sed 's/\//\\\\\//g'`
+
+Doxyfile.gen: doc/Doxyfile
+ cat $< | sed "s/%srcdir%/$(ESC_srcdir)/g" \
+ | sed "s/%builddir%/$(ESC_top_builddir)/g" > $@
+
+doc/html/index.html: Doxyfile.gen $(all_files)
+ BUILD_DIR=`cd $(top_builddir); pwd`; \
+ (cd $(srcdir); doxygen $$BUILD_DIR/Doxyfile.gen)
+
+# The intention with the following rules is that all of the Doxygen
+# documentation (both HTML and PDF) is built locally before distcheck is
+# run, since it's quite possible that the user will not have a complete
+# TeX + Doxygen + dot environment on their own system.
+
+doc/refman.pdf: doc/html/index.html
+ (cd doc/latex && make)
+ cp doc/latex/refman.pdf $@
+
+docs: pdf doc/refman.pdf
+else
+docs: pdf
+endif
+
+libs:
+ @echo Building dependency libs and installing in /usr/local/stow ...
+ git submodule update --init
+ (cd lib; make)
+
+report: all
+ -rm -fr build
+ lcov -d $(shell pwd) --zerocounters
+ -mkdir doc/report
+ lcov -c -i -d $(shell pwd) -o doc/report/ledger_base.info
+ make fullcheck
+ lcov -c -d $(shell pwd) --checksum -o doc/report/ledger_test.info
+ lcov -a doc/report/ledger_base.info \
+ -a doc/report/ledger_test.info -o doc/report/ledger_total.info
+ lcov --extract doc/report/ledger_total.info '*src/ledger/*' \
+ -o doc/report/ledger_cov.info
+ genhtml -o doc/report doc/report/ledger_cov.info
+ @echo Coverage reported generated\; now open doc/report/index.html
+
+# Makefile.am ends here
diff --git a/autogen.sh b/tools/autogen.sh
index a8b63eff..a8b63eff 100755
--- a/autogen.sh
+++ b/tools/autogen.sh
diff --git a/tools/average b/tools/average
new file mode 100755
index 00000000..0e95c1c5
--- /dev/null
+++ b/tools/average
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+
+import getopt
+import time
+import string
+import sys
+import os
+
+count = 10
+
+opts, args = getopt.getopt(sys.argv[1:], "n:")
+for opt in opts:
+ if opt[0] == "-n":
+ count = int(opt[1])
+
+length = 0.0
+
+i = 0
+while i < count:
+ begin = time.time()
+ cmd = '"' + string.join(args, '" "') + '"';
+ os.system(cmd)
+ length += time.time() - begin
+ i += 1
+
+print >> sys.stderr, length / count
diff --git a/tools/configure.ac b/tools/configure.ac
new file mode 100644
index 00000000..b508eb21
--- /dev/null
+++ b/tools/configure.ac
@@ -0,0 +1,427 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.61)
+
+m4_include([version.m4])
+
+AC_INIT([ledger],[VERSION_NUMBER],[johnw@newartisans.com])
+
+AC_CONFIG_AUX_DIR([.])
+AM_INIT_AUTOMAKE([dist-bzip2 foreign])
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_CONFIG_SRCDIR([src/main.cc])
+AC_CONFIG_HEADER([config.h])
+
+# Checks for programs.
+AC_USE_SYSTEM_EXTENSIONS
+AC_PROG_CXX
+AC_PROG_MAKE_SET
+AC_PROG_LIBTOOL
+AM_GNU_GETTEXT
+AM_GNU_GETTEXT_VERSION([0.17])
+
+# Checks for emacs lisp path
+AM_PATH_LISPDIR
+
+# Check for options
+AC_ARG_ENABLE(debug,
+ [ --enable-debug Turn on debugging],
+ [case "${enableval}" in
+ yes) debug=true ;;
+ no) debug=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
+ esac],[debug=false])
+
+if [ test x$debug = xtrue ]; then
+ AC_DEFINE([DEBUG_MODE], [1], [Whether debugging is enabled])
+fi
+AM_CONDITIONAL(DEBUG, test x$debug = xtrue)
+
+AC_ARG_ENABLE(pch,
+ [ --enable-pch Use GCC 4.x pre-compiled headers],
+ [case "${enableval}" in
+ yes) pch=true ;;
+ no) pch=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pch) ;;
+ esac],[pch=false])
+
+if [ test x$pch = xtrue ]; then
+ AC_DEFINE([USE_PCH], [1], [Whether pre-compiled headers are being used])
+fi
+AM_CONDITIONAL(USE_PCH, test x$pch = xtrue)
+
+AC_ARG_ENABLE(doxygen,
+ [ --enable-doxygen Turns on generation of code documentation],
+ [case "${enableval}" in
+ yes) doxygen=true ;;
+ no) doxygen=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-doxygen) ;;
+ esac],[doxygen=false])
+
+AM_CONDITIONAL(USE_DOXYGEN, test x$doxygen = xtrue)
+
+AC_ARG_ENABLE(python,
+ [ --enable-python Turn on Python support (experimental)],
+ [case "${enableval}" in
+ yes) python=true ;;
+ no) python=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-python) ;;
+ esac],[python=false])
+
+AC_ARG_WITH(boost-suffix,
+ [ --with-boost-suffix=X Append X to the Boost library names],
+ [BOOST_SUFFIX="${withval}"],
+ [BOOST_SUFFIX=""])
+
+AC_SUBST([BOOST_SUFFIX], $BOOST_SUFFIX)
+
+# check if UNIX pipes are available
+AC_CACHE_CHECK(
+ [if pipes can be used],
+ [pipes_avail_cv_],
+ [AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <sys/types.h>
+ #include <sys/wait.h>
+ #include <unistd.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <stdio.h>]],
+ [[int status, pfd[2];
+ status = pipe(pfd);
+ status = fork();
+ if (status < 0) {
+ ;
+ } else if (status == 0) {
+ char *arg0 = NULL;
+
+ status = dup2(pfd[0], STDIN_FILENO);
+
+ close(pfd[1]);
+ close(pfd[0]);
+
+ execlp("", arg0, (char *)0);
+ perror("execl");
+ exit(1);
+ } else {
+ close(pfd[0]);
+ }]])],
+ [pipes_avail_cv_=true],
+ [pipes_avail_cv_=false])
+ AC_LANG_POP])
+
+if [test x$pipes_avail_cv_ = xtrue ]; then
+ AC_DEFINE([HAVE_UNIX_PIPES], [1], [Whether UNIX pipes are available])
+fi
+
+# check for gmp
+AC_CACHE_CHECK(
+ [if GMP is available],
+ [libgmp_avail_cv_],
+ [libgmp_save_libs=$LIBS
+ LIBS="-lgmp $LIBS"
+ AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <gmp.h>]], [[mpz_t bar;
+ mpz_init(bar);
+ mpz_clear(bar);]])],[libgmp_avail_cv_=true],[libgmp_avail_cv_=false])
+ AC_LANG_POP
+ LIBS=$libgmp_save_libs])
+
+if [test x$libgmp_avail_cv_ = xtrue ]; then
+ LIBS="-lgmp $LIBS"
+else
+ AC_MSG_FAILURE("Could not find gmp library (set CPPFLAGS and LDFLAGS?)")
+fi
+
+# check for mpfr
+AC_CACHE_CHECK(
+ [if MPFR is available],
+ [libmpfr_avail_cv_],
+ [libmpfr_save_libs=$LIBS
+ LIBS="-lmpfr $LIBS"
+ AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <mpfr.h>]], [[mpfr_t bar;
+ mpfr_init(bar);
+ char * buf = NULL;
+ mpfr_asprintf(&buf, "%Rf", bar);
+ mpfr_clear(bar);]])],[libmpfr_avail_cv_=true],[libmpfr_avail_cv_=false])
+ AC_LANG_POP
+ LIBS=$libmpfr_save_libs])
+
+if [test x$libmpfr_avail_cv_ = xtrue ]; then
+ LIBS="-lmpfr $LIBS"
+else
+ AC_MSG_FAILURE("Could not find mpfr library 2.4.0 or higher (set CPPFLAGS and LDFLAGS?)")
+fi
+
+# check for edit
+AC_CACHE_CHECK(
+ [if libedit is available],
+ [libedit_avail_cv_],
+ [libedit_save_libs=$LIBS
+ LIBS="-ledit $LIBS"
+ AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM(
+ [[#include <stdlib.h>
+ #include <stdio.h>
+ #include <editline/readline.h>]],
+ [[rl_readline_name = const_cast<char *>("foo");
+ char * line = readline(const_cast<char *>("foo: "));
+ free(line);]])],[libedit_avail_cv_=true],[libedit_avail_cv_=false])
+ AC_LANG_POP
+ LIBS=$libedit_save_libs])
+
+if [test x$libedit_avail_cv_ = xtrue ]; then
+ LIBS="-ledit $LIBS"
+ AC_DEFINE([HAVE_LIBEDIT], [1], [If the libedit library is available])
+fi
+
+# check for boost_regex
+AC_CACHE_CHECK(
+ [if boost_regex is available],
+ [boost_regex_avail_cv_],
+ [boost_regex_save_libs=$LIBS
+ LIBS="-lboost_regex$BOOST_SUFFIX $LIBS"
+ AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <boost/regex.hpp>]],
+ [[boost::regex foo_regexp("Hello, world!");]])],
+ [boost_regex_avail_cv_=true],
+ [boost_regex_avail_cv_=false])
+ AC_LANG_POP
+ LIBS=$boost_regex_save_libs])
+
+if [test x$boost_regex_avail_cv_ = xtrue ]; then
+ LIBS="-lboost_regex$BOOST_SUFFIX $LIBS"
+else
+ AC_MSG_FAILURE("Could not find boost_regex library (set CPPFLAGS and LDFLAGS?)")
+fi
+
+AC_CACHE_CHECK(
+ [if boost_regex w/ICU is available],
+ [boost_regex_icu_avail_cv_],
+ [boost_regex_icu_save_libs=$LIBS
+ LIBS="-licuuc $LIBS"
+ AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <boost/regex/icu.hpp>
+ using namespace boost;]],
+ [[std::string text = "Ðктивы";
+ u32regex r = make_u32regex("активы", regex::perl | regex::icase);
+ return u32regex_search(text, r) ? 0 : 1;]])],
+ [boost_regex_icu_avail_cv_=true],
+ [boost_regex_icu_avail_cv_=false])
+ AC_LANG_POP
+ LIBS=$boost_regex_icu_save_libs])
+
+if [test x$boost_regex_icu_avail_cv_ = xtrue ]; then
+ AC_DEFINE([HAVE_BOOST_REGEX_UNICODE], [1], [If the boost_regex library w/ICU is available])
+ LIBS="-licuuc $LIBS"
+fi
+
+# check for boost_date_time
+AC_CACHE_CHECK(
+ [if boost_date_time is available],
+ [boost_date_time_cpplib_avail_cv_],
+ [boost_date_time_save_libs=$LIBS
+ LIBS="-lboost_date_time$BOOST_SUFFIX $LIBS"
+ AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <boost/date_time/posix_time/posix_time.hpp>
+ #include <boost/date_time/gregorian/gregorian.hpp>
+ #include <boost/date_time/local_time_adjustor.hpp>
+ #include <boost/date_time/time_duration.hpp>
+
+ using namespace boost::posix_time;
+ using namespace boost::date_time;
+
+ #include <ctime>
+
+ inline ptime time_to_system_local(const ptime& when) {
+ struct std::tm tm_gmt = to_tm(when);
+ return from_time_t(mktime(&tm_gmt));
+ }]],
+ [[ptime t10 = ptime(boost::gregorian::from_string("2007-01-15"),
+ ptime::time_duration_type());
+
+ ptime t12 = time_to_system_local(t10);
+
+ return t10 != t12;]])],
+ [boost_date_time_cpplib_avail_cv_=true],
+ [boost_date_time_cpplib_avail_cv_=false])
+ AC_LANG_POP
+ LIBS=$boost_date_time_save_libs])
+
+if [test x$boost_date_time_cpplib_avail_cv_ = xtrue ]; then
+ LIBS="-lboost_date_time$BOOST_SUFFIX $LIBS"
+else
+ AC_MSG_FAILURE("Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)")
+fi
+
+# check for boost_filesystem
+AC_CACHE_CHECK(
+ [if boost_filesystem is available],
+ [boost_filesystem_cpplib_avail_cv_],
+ [boost_filesystem_save_libs=$LIBS
+ LIBS="-lboost_filesystem$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
+ AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <boost/filesystem/path.hpp>]],
+ [[boost::filesystem::path this_path("Hello");]])],
+ [boost_filesystem_cpplib_avail_cv_=true],
+ [boost_filesystem_cpplib_avail_cv_=false])
+ AC_LANG_POP
+ LIBS=$boost_filesystem_save_libs])
+
+if [test x$boost_filesystem_cpplib_avail_cv_ = xtrue ]; then
+ LIBS="-lboost_filesystem$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
+else
+ AC_MSG_FAILURE("Could not find boost_filesystem library (set CPPFLAGS and LDFLAGS?)")
+fi
+
+# check for boost_iostreams
+AC_CACHE_CHECK(
+ [if boost_iostreams is available],
+ [boost_iostreams_cpplib_avail_cv_],
+ [boost_iostreams_save_libs=$LIBS
+ LIBS="-lboost_iostreams$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
+ AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <boost/iostreams/device/file_descriptor.hpp>
+ #include <boost/iostreams/stream.hpp>]],
+ [[namespace io = boost::iostreams;
+ typedef io::stream<io::file_descriptor_sink> ofdstream;
+ ofdstream outstream(1);]])],
+ [boost_iostreams_cpplib_avail_cv_=true],
+ [boost_iostreams_cpplib_avail_cv_=false])
+ AC_LANG_POP
+ LIBS=$boost_iostreams_save_libs])
+
+if [test x$boost_iostreams_cpplib_avail_cv_ = xtrue ]; then
+ LIBS="-lboost_iostreams$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
+else
+ AC_MSG_FAILURE("Could not find boost_iostreams library (set CPPFLAGS and LDFLAGS?)")
+fi
+
+# check for boost_serialization
+AC_CACHE_CHECK(
+ [if boost_serialization is available],
+ [boost_serialization_cpplib_avail_cv_],
+ [boost_serialization_save_libs=$LIBS
+ LIBS="-lboost_serialization$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
+ AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <boost/archive/binary_oarchive.hpp>
+ #include <iostream>
+ struct foo {
+ int a;
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int) {
+ ar & a;
+ }
+ };]],
+ [[boost::archive::binary_oarchive oa(std::cout);
+ foo x;
+ oa << x;]])],
+ [boost_serialization_cpplib_avail_cv_=true],
+ [boost_serialization_cpplib_avail_cv_=false])
+ AC_LANG_POP
+ LIBS=$boost_serialization_save_libs])
+
+if [test x$boost_serialization_cpplib_avail_cv_ = xtrue ]; then
+ AC_DEFINE([HAVE_BOOST_SERIALIZATION], [1], [Whether Boost.Serialization is available])
+ LIBS="-lboost_serialization$BOOST_SUFFIX $LIBS"
+fi
+AM_CONDITIONAL(HAVE_BOOST_SERIALIZATION, test x$boost_serialization_cpplib_avail_cv_ = xtrue)
+
+# check for Python
+if [ test x$python = xtrue ]; then
+ AM_PATH_PYTHON(2.4,, :)
+ if [test "$PYTHON" != :]; then
+ AM_CONDITIONAL(HAVE_PYTHON, true)
+ AC_CACHE_CHECK(
+ [if boost_python is available],
+ [boost_python_cpplib_avail_cv_],
+ [boost_python_save_libs=$LIBS
+ LIBS="-lboost_python$BOOST_SUFFIX -lpython$PYTHON_VERSION $LIBS"
+ AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <boost/python.hpp>
+ using namespace boost::python;
+ class foo {};
+ BOOST_PYTHON_MODULE(samp) {
+ class_< foo > ("foo") ;
+ }]],
+ [[return 0]])],
+ [boost_python_cpplib_avail_cv_=true],
+ [boost_python_cpplib_avail_cv_=false])
+ AC_LANG_POP
+ LIBS=$boost_python_save_libs])
+
+ if [ test x$boost_python_cpplib_avail_cv_ = xtrue ]; then
+ AC_DEFINE([HAVE_BOOST_PYTHON], [1], [Whether Boost.Python is available])
+ LIBS="-lboost_python$BOOST_SUFFIX -lpython$PYTHON_VERSION $LIBS"
+ fi
+ else
+ AM_CONDITIONAL(HAVE_PYTHON, false)
+ fi
+ AM_CONDITIONAL(HAVE_BOOST_PYTHON, test x$boost_python_cpplib_avail_cv_ = xtrue)
+else
+ AM_CONDITIONAL(HAVE_PYTHON, false)
+ AM_CONDITIONAL(HAVE_BOOST_PYTHON, false)
+fi
+
+# check for CppUnit
+AC_CACHE_CHECK(
+ [if cppunit is available],
+ [cppunit_avail_cv_],
+ [cppunit_save_libs=$LIBS
+ LIBS="-lcppunit $LIBS"
+ AC_LANG_PUSH(C++)
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <cppunit/CompilerOutputter.h>
+ #include <cppunit/TestResult.h>
+ #include <cppunit/TestResultCollector.h>
+ #include <cppunit/TestRunner.h>
+ #include <cppunit/TextTestProgressListener.h>
+ #include <cppunit/BriefTestProgressListener.h>
+ #include <cppunit/XmlOutputter.h>
+ #include <cppunit/extensions/TestFactoryRegistry.h>]],
+ [[CPPUNIT_NS::TestResult controller;
+ CPPUNIT_NS::TestResultCollector result;]])],
+ [cppunit_avail_cv_=true],
+ [cppunit_avail_cv_=false])
+ AC_LANG_POP
+ LIBS=$cppunit_save_libs])
+
+AM_CONDITIONAL(HAVE_CPPUNIT, test x$cppunit_avail_cv_ = xtrue)
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_STAT
+AC_CHECK_HEADERS([langinfo.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_TYPE_SIZE_T
+AC_STRUCT_TM
+
+# Checks for library functions.
+#AC_FUNC_MKTIME
+#AC_FUNC_STAT
+#AC_FUNC_STRFTIME
+AC_CHECK_FUNCS([access realpath getpwuid getpwnam isatty])
+
+# Pepare the Makefiles
+AC_CONFIG_FILES([Makefile po/Makefile.in intl/Makefile])
+AC_OUTPUT
diff --git a/tools/excludes b/tools/excludes
new file mode 100644
index 00000000..dc56eacc
--- /dev/null
+++ b/tools/excludes
@@ -0,0 +1,47 @@
+*.la
+*.lo
+*.o
+.deps/
+.git*
+.git/
+.libs/
+Makefile
+Makefile.in
+RegressionTests
+aclocal.m4
+autom4te.cache/
+build/
+config.guess
+config.h
+config.h.in
+config.h.in~
+config.log
+config.rpath
+config.status
+config.sub
+configure
+data_tests
+depcomp
+doc/.dirstamp
+doc/ledger.info
+elisp-comp
+expr_tests
+install-sh
+intl/
+ledger
+ledger.so
+lib/cppunit/
+lib/utfcpp/
+libtool
+ltmain.sh
+m4/
+make.sh
+math_tests
+missing
+po/
+report_tests
+src/system.hh.gch
+stamp-h1
+texinfo.tex
+util_tests
+version.m4
diff --git a/tools/pre-commit b/tools/pre-commit
new file mode 100755
index 00000000..c049b8f0
--- /dev/null
+++ b/tools/pre-commit
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+# Exit with status 1 if any command below fails
+set -e
+
+# Exit if it's not a branch we're interested in being thorough about
+if echo $(git rev-parse --symbolic-full-name HEAD) | \
+ egrep -q '^refs/heads/(next|t/)'; then
+ exit 0
+fi
+
+# These are the locations I keep my temporary source and build trees in
+PRODUCTS=$(./acprep products) # generates a build directory name such as
+ # ~/Products/ledger
+TMPDIR=$PRODUCTS/pre-commit
+MIRROR=$PRODUCTS/pre-commit-mirror
+
+# Checkout a copy of the current index into MIRROR
+git checkout-index --prefix=$MIRROR/ -af
+
+# Remove files from MIRROR which are no longer present in the index
+git diff-index --cached --name-only --diff-filter=D -z HEAD | \
+ (cd $MIRROR && xargs -0 rm -f --)
+
+# Copy only _changed files_ from MIRROR to TMPDIR, without copying
+# timestamps. This includes copying over new files, and deleting
+# removed ones. This way, "make check" will only rebuild what is
+# necessary to validate the commit.
+rsync -rlpgoDOc --delete --exclude-from=tools/excludes $MIRROR/ $TMPDIR/
+
+# Everything else happens in the temporary build tree
+if [ ! -f $TMPDIR/lib/utfcpp/source/utf8.h ]; then
+ rsync -a --delete lib/utfcpp/ $TMPDIR/lib/utfcpp/
+fi
+cd $TMPDIR
+
+# Make sure there is a current Makefile. Regeneration of Makefile
+# happens automatically, but if myacprep or acprep changes, we want to
+# regenerate everything manually. If the user doesn't have acprep, look
+# for other common autoconf-related script files.
+if [ ! -f Makefile -o \
+ Makefile.in -nt Makefile -o \
+ configure -nt Makefile -o \
+ Makefile.am -nt Makefile.in -o \
+ configure.ac -nt configure -o \
+ \( -f acprep -a acprep -nt Makefile \) ]
+then
+ if [ -f acprep ]; then
+ ./acprep default --local
+ elif [ -f autogen.sh ]; then
+ sh autogen.sh && ./configure
+ else
+ autoreconf && ./configure
+ fi
+fi
+
+# Finally, (re)build this proposed source tree and see if it passes
+# muster.
+nice -n 20 make check
+
+exit 0
diff --git a/tools/proof b/tools/proof
new file mode 100755
index 00000000..c41745b6
--- /dev/null
+++ b/tools/proof
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+set -e
+
+cd ~/src/ledger
+
+VERSION=$(git describe --all --long)
+
+if [[ -f ~/Products/last-proofed && \
+ $(< ~/Products/last-proofed) = $VERSION ]]; then
+ echo "No need to run tools/proof again"
+ exit 0
+fi
+
+rm -fr ~/Products/ledger*
+
+time ./acprep -j16 --warn proof 2>&1 | tee ~/Desktop/proof.log
+
+if egrep -q '(ERROR|CRITICAL)' ~/Desktop/proof.log; then
+ if [[ "$1" = "--alert" ]]; then
+ notify "Ledger proof build FAILED"
+ else
+ echo "Ledger proof build FAILED"
+ exit 1
+ fi
+else
+ echo "Ledger proof build succeeded"
+ echo $VERSION > ~/Products/last-proofed
+ mv ~/Desktop/proof.log /tmp
+fi
+
+exit 0
diff --git a/tools/push b/tools/push
new file mode 100755
index 00000000..778f770b
--- /dev/null
+++ b/tools/push
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+set -e
+
+(cd plan/data; git push)
+(cd plan; git commit -a -m "Update TODO files" && git push)
+git checkout master
+git merge --no-ff next
+git checkout next
+git rebase master
+git push
+git checkout master
+./acprep -j16 opt upload
+mv *.dmg* build
+git checkout next
diff --git a/tools/rename.sh b/tools/rename.sh
new file mode 100755
index 00000000..7d27d8f8
--- /dev/null
+++ b/tools/rename.sh
@@ -0,0 +1,67 @@
+#!/bin/zsh
+
+git reset --hard
+
+rm -f src/system.hh.gch ledger
+
+for file in *(.) contrib/*(.) doc/*(.) plan/*(.) python/*(.) src/*(.) test/*(.) test/*/*(.) tools/*(.)
+do
+ echo Renaming items in $file ...
+
+ perl -i -pe 's/xact/fazole/g;' $file 2> /dev/null
+ perl -i -pe 's/XACT/FAZOLE/g;' $file 2> /dev/null
+ perl -i -pe 's/Xact/Fazole/g;' $file 2> /dev/null
+ perl -i -pe 's/xacts/fazoles/g;' $file 2> /dev/null
+ perl -i -pe 's/XACTS/FAZOLES/g;' $file 2> /dev/null
+ perl -i -pe 's/Xacts/Fazoles/g;' $file 2> /dev/null
+
+ perl -i -pe 's/transaction/brazole/g;' $file 2> /dev/null
+ perl -i -pe 's/TRANSACTION/BRAZOLE/g;' $file 2> /dev/null
+ perl -i -pe 's/Transaction/Brazole/g;' $file 2> /dev/null
+ perl -i -pe 's/transactions/brazoles/g;' $file 2> /dev/null
+ perl -i -pe 's/TRANSACTIONS/BRAZOLES/g;' $file 2> /dev/null
+ perl -i -pe 's/Transactions/Brazoles/g;' $file 2> /dev/null
+
+ perl -i -pe 's/entry/xact/g;' $file 2> /dev/null
+ perl -i -pe 's/ENTRY/XACT/g;' $file 2> /dev/null
+ perl -i -pe 's/Entry/Xact/g;' $file 2> /dev/null
+ perl -i -pe 's/entries/xacts/g;' $file 2> /dev/null
+ perl -i -pe 's/ENTRIES/XACTS/g;' $file 2> /dev/null
+ perl -i -pe 's/Entries/Xacts/g;' $file 2> /dev/null
+ perl -i -pe 's/entrys/xacts/g;' $file 2> /dev/null
+ perl -i -pe 's/ENTRYS/XACTS/g;' $file 2> /dev/null
+ perl -i -pe 's/Entrys/Xacts/g;' $file 2> /dev/null
+
+ perl -i -pe 's/fazoles/posts/g;' $file 2> /dev/null
+ perl -i -pe 's/FAZOLES/POSTS/g;' $file 2> /dev/null
+ perl -i -pe 's/Fazoles/Posts/g;' $file 2> /dev/null
+ perl -i -pe 's/fazole/post/g;' $file 2> /dev/null
+ perl -i -pe 's/FAZOLE/POST/g;' $file 2> /dev/null
+ perl -i -pe 's/Fazole/Post/g;' $file 2> /dev/null
+
+ perl -i -pe 's/brazoles/postings/g;' $file 2> /dev/null
+ perl -i -pe 's/BRAZOLES/POSTINGS/g;' $file 2> /dev/null
+ perl -i -pe 's/Brazoles/Postings/g;' $file 2> /dev/null
+ perl -i -pe 's/brazole/posting/g;' $file 2> /dev/null
+ perl -i -pe 's/BRAZOLE/POSTING/g;' $file 2> /dev/null
+ perl -i -pe 's/Brazole/Posting/g;' $file 2> /dev/null
+
+ perl -i -pe 's/\@dirxact/\@direntry/g;' $file 2> /dev/null
+ perl -i -pe 's/\@end dirxact/\@end direntry/g;' $file 2> /dev/null
+done
+
+mv src/xact.h src/fazole.h
+mv src/xact.cc src/fazole.cc
+mv src/entry.h src/xact.h
+mv src/entry.cc src/xact.cc
+mv src/fazole.h src/post.h
+mv src/fazole.cc src/post.cc
+
+mv src/py_xact.py src/fazole.py
+mv src/py_entry.py src/py_xact.py
+mv src/fazole.py src/py_post.py
+
+ln -sf ~/Products/ledger/ledger .
+
+tools/myacprep
+
diff --git a/tools/speedcmp b/tools/speedcmp
new file mode 100755
index 00000000..a040724e
--- /dev/null
+++ b/tools/speedcmp
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# ex: speedcmp ledger ledger-2.4 50
+
+export LEDGER_FILE=$PWD/tools/temp.dat
+export LEDGER_CACHE=$PWD/tools/temp.cache
+
+count=$1
+shift 1
+
+for i in "$@"; do
+ echo -n "textual $i: "
+ average -n $count $i -o /dev/null -f $LEDGER reg rent
+
+ rm -f $LEDGER_CACHE; $i -o /dev/null reg rent > /dev/null 2>&1
+ echo -n "binary $i: "
+ average -n $count $i -o /dev/null reg rent
+done
diff --git a/tools/times.sh b/tools/times.sh
new file mode 100755
index 00000000..444da993
--- /dev/null
+++ b/tools/times.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+time test/RegressTests.py ./ledger test/regress
+time test/RegressTests.py ./ledger test/regress --verify
+time test/RegressTests.py ./ledger test/regress --gmalloc
+time test/RegressTests.py ./ledger test/regress --verify --gmalloc
diff --git a/util.h b/util.h
deleted file mode 100644
index 21008a22..00000000
--- a/util.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef _UTIL_H
-#define _UTIL_H
-
-#include <iostream>
-
-#if defined __FreeBSD__ && __FreeBSD__ <=4
-// FreeBSD has a broken isspace macro, so dont use it
-#undef isspace(c)
-#endif
-
-#if defined(__GNUG__) && __GNUG__ < 3
-namespace std {
- inline ostream & right (ostream & i) {
- i.setf(i.right, i.adjustfield);
- return i;
- }
- inline ostream & left (ostream & i) {
- i.setf(i.left, i.adjustfield);
- return i;
- }
-}
-typedef unsigned long istream_pos_type;
-typedef unsigned long ostream_pos_type;
-#else
-typedef std::istream::pos_type istream_pos_type;
-typedef std::ostream::pos_type ostream_pos_type;
-#endif
-
-inline char * skip_ws(char * ptr) {
- while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')
- ptr++;
- return ptr;
-}
-
-inline char peek_next_nonws(std::istream& in) {
- char c = in.peek();
- while (! in.eof() && std::isspace(c)) {
- in.get(c);
- c = in.peek();
- }
- return c;
-}
-
-#define READ_INTO(str, targ, size, var, cond) { \
- char * _p = targ; \
- var = str.peek(); \
- while (! str.eof() && var != '\n' && (cond) && _p - targ < size) { \
- str.get(var); \
- if (str.eof()) \
- break; \
- if (var == '\\') { \
- str.get(var); \
- if (in.eof()) \
- break; \
- } \
- *_p++ = var; \
- var = str.peek(); \
- } \
- *_p = '\0'; \
-}
-
-#endif // _UTIL_H
diff --git a/valexpr.cc b/valexpr.cc
deleted file mode 100644
index 4fed821e..00000000
--- a/valexpr.cc
+++ /dev/null
@@ -1,1988 +0,0 @@
-#include "valexpr.h"
-#include "walk.h"
-#include "error.h"
-#include "datetime.h"
-#include "debug.h"
-#include "util.h"
-
-namespace ledger {
-
-value_expr amount_expr;
-value_expr total_expr;
-
-std::auto_ptr<scope_t> global_scope;
-datetime_t terminus;
-
-details_t::details_t(const transaction_t& _xact)
- : entry(_xact.entry), xact(&_xact), account(xact_account(_xact))
-{
- DEBUG_PRINT("ledger.memory.ctors", "ctor details_t");
-}
-
-bool compute_amount(value_expr_t * expr, amount_t& amt,
- const transaction_t * xact, value_expr_t * context)
-{
- value_t result;
- try {
- expr->compute(result, xact ? details_t(*xact) : details_t(), context);
- result.cast(value_t::AMOUNT);
- amt = *((amount_t *) result.data);
- }
- catch (error * err) {
- if (err->context.empty() ||
- ! dynamic_cast<valexpr_context *>(err->context.back()))
- err->context.push_back(new valexpr_context(expr));
- error_context * last = err->context.back();
- if (valexpr_context * ctxt = dynamic_cast<valexpr_context *>(last)) {
- ctxt->expr = expr->acquire();
- ctxt->desc = "While computing amount expression:";
- }
- throw err;
- }
- return true;
-}
-
-value_expr_t::~value_expr_t()
-{
- DEBUG_PRINT("ledger.memory.dtors", "dtor value_expr_t " << this);
-
- DEBUG_PRINT("ledger.valexpr.memory", "Destroying " << this);
- assert(refc == 0);
-
- if (left)
- left->release();
-
- switch (kind) {
- case F_CODE_MASK:
- case F_PAYEE_MASK:
- case F_NOTE_MASK:
- case F_ACCOUNT_MASK:
- case F_SHORT_ACCOUNT_MASK:
- case F_COMMODITY_MASK:
- assert(mask);
- delete mask;
- break;
-
- case CONSTANT:
- assert(value);
- delete value;
- break;
-
- default:
- if (kind > TERMINALS && right)
- right->release();
- break;
- }
-}
-
-namespace {
- int count_leaves(value_expr_t * expr)
- {
- int count = 0;
- if (expr->kind != value_expr_t::O_COM) {
- count = 1;
- } else {
- count += count_leaves(expr->left);
- count += count_leaves(expr->right);
- }
- return count;
- }
-
- value_expr_t * reduce_leaves(value_expr_t * expr, const details_t& details,
- value_expr_t * context)
- {
- if (! expr)
- return NULL;
-
- value_expr temp;
-
- if (expr->kind != value_expr_t::O_COM) {
- if (expr->kind < value_expr_t::TERMINALS) {
- temp.reset(expr);
- } else {
- temp.reset(new value_expr_t(value_expr_t::CONSTANT));
- temp->value = new value_t;
- expr->compute(*(temp->value), details, context);
- }
- } else {
- temp.reset(new value_expr_t(value_expr_t::O_COM));
- temp->set_left(reduce_leaves(expr->left, details, context));
- temp->set_right(reduce_leaves(expr->right, details, context));
- }
- return temp.release();
- }
-
- value_expr_t * find_leaf(value_expr_t * context, int goal, int& found)
- {
- if (! context)
- return NULL;
-
- if (context->kind != value_expr_t::O_COM) {
- if (goal == found++)
- return context;
- } else {
- value_expr_t * expr = find_leaf(context->left, goal, found);
- if (expr)
- return expr;
- expr = find_leaf(context->right, goal, found);
- if (expr)
- return expr;
- }
- return NULL;
- }
-}
-
-void value_expr_t::compute(value_t& result, const details_t& details,
- value_expr_t * context) const
-{
- try {
- switch (kind) {
- case ARG_INDEX:
- throw new compute_error("Cannot directly compute an arg_index");
-
- case CONSTANT:
- assert(value);
- result = *value;
- break;
-
- case F_NOW:
- result = terminus;
- break;
-
- case AMOUNT:
- if (details.xact) {
- if (transaction_has_xdata(*details.xact) &&
- transaction_xdata_(*details.xact).dflags & TRANSACTION_COMPOUND)
- result = transaction_xdata_(*details.xact).value;
- else
- result = details.xact->amount;
- }
- else if (details.account && account_has_xdata(*details.account)) {
- result = account_xdata(*details.account).value;
- }
- else {
- result = 0L;
- }
- break;
-
- case PRICE:
- if (details.xact) {
- bool set = false;
- if (transaction_has_xdata(*details.xact)) {
- transaction_xdata_t& xdata(transaction_xdata_(*details.xact));
- if (xdata.dflags & TRANSACTION_COMPOUND) {
- result = xdata.value.price();
- set = true;
- }
- }
- if (! set)
- result = details.xact->amount.price();
- }
- else if (details.account && account_has_xdata(*details.account)) {
- result = account_xdata(*details.account).value.price();
- }
- else {
- result = 0L;
- }
- break;
-
- case COST:
- if (details.xact) {
- bool set = false;
- if (transaction_has_xdata(*details.xact)) {
- transaction_xdata_t& xdata(transaction_xdata_(*details.xact));
- if (xdata.dflags & TRANSACTION_COMPOUND) {
- result = xdata.value.cost();
- set = true;
- }
- }
-
- if (! set) {
- if (details.xact->cost)
- result = *details.xact->cost;
- else
- result = details.xact->amount;
- }
- }
- else if (details.account && account_has_xdata(*details.account)) {
- result = account_xdata(*details.account).value.cost();
- }
- else {
- result = 0L;
- }
- break;
-
- case TOTAL:
- if (details.xact && transaction_has_xdata(*details.xact))
- result = transaction_xdata_(*details.xact).total;
- else if (details.account && account_has_xdata(*details.account))
- result = account_xdata(*details.account).total;
- else
- result = 0L;
- break;
- case PRICE_TOTAL:
- if (details.xact && transaction_has_xdata(*details.xact))
- result = transaction_xdata_(*details.xact).total.price();
- else if (details.account && account_has_xdata(*details.account))
- result = account_xdata(*details.account).total.price();
- else
- result = 0L;
- break;
- case COST_TOTAL:
- if (details.xact && transaction_has_xdata(*details.xact))
- result = transaction_xdata_(*details.xact).total.cost();
- else if (details.account && account_has_xdata(*details.account))
- result = account_xdata(*details.account).total.cost();
- else
- result = 0L;
- break;
-
- case VALUE_EXPR:
- if (amount_expr.get())
- amount_expr->compute(result, details, context);
- else
- result = 0L;
- break;
- case TOTAL_EXPR:
- if (total_expr.get())
- total_expr->compute(result, details, context);
- else
- result = 0L;
- break;
-
- case DATE:
- if (details.xact && transaction_has_xdata(*details.xact) &&
- transaction_xdata_(*details.xact).date)
- result = transaction_xdata_(*details.xact).date;
- else if (details.xact)
- result = details.xact->date();
- else if (details.entry)
- result = details.entry->date();
- else
- result = terminus;
- break;
-
- case ACT_DATE:
- if (details.xact && transaction_has_xdata(*details.xact) &&
- transaction_xdata_(*details.xact).date)
- result = transaction_xdata_(*details.xact).date;
- else if (details.xact)
- result = details.xact->actual_date();
- else if (details.entry)
- result = details.entry->actual_date();
- else
- result = terminus;
- break;
-
- case EFF_DATE:
- if (details.xact && transaction_has_xdata(*details.xact) &&
- transaction_xdata_(*details.xact).date)
- result = transaction_xdata_(*details.xact).date;
- else if (details.xact)
- result = details.xact->effective_date();
- else if (details.entry)
- result = details.entry->effective_date();
- else
- result = terminus;
- break;
-
- case CLEARED:
- if (details.xact)
- result = details.xact->state == transaction_t::CLEARED;
- else
- result = false;
- break;
- case PENDING:
- if (details.xact)
- result = details.xact->state == transaction_t::PENDING;
- else
- result = false;
- break;
-
- case REAL:
- if (details.xact)
- result = ! (details.xact->flags & TRANSACTION_VIRTUAL);
- else
- result = true;
- break;
-
- case ACTUAL:
- if (details.xact)
- result = ! (details.xact->flags & TRANSACTION_AUTO);
- else
- result = true;
- break;
-
- case INDEX:
- if (details.xact && transaction_has_xdata(*details.xact))
- result = long(transaction_xdata_(*details.xact).index + 1);
- else if (details.account && account_has_xdata(*details.account))
- result = long(account_xdata(*details.account).count);
- else
- result = 0L;
- break;
-
- case COUNT:
- if (details.xact && transaction_has_xdata(*details.xact))
- result = long(transaction_xdata_(*details.xact).index + 1);
- else if (details.account && account_has_xdata(*details.account))
- result = long(account_xdata(*details.account).total_count);
- else
- result = 0L;
- break;
-
- case DEPTH:
- if (details.account)
- result = long(details.account->depth);
- else
- result = 0L;
- break;
-
- case F_PRICE: {
- int arg_index = 0;
- value_expr_t * expr = find_leaf(context, 0, arg_index);
- expr->compute(result, details, context);
- result = result.price();
- break;
- }
-
- case F_DATE: {
- int arg_index = 0;
- value_expr_t * expr = find_leaf(context, 0, arg_index);
- expr->compute(result, details, context);
- result = result.date();
- break;
- }
-
- case F_DATECMP: {
- int arg_index = 0;
- value_expr_t * expr = find_leaf(context, 0, arg_index);
- expr->compute(result, details, context);
- result = result.date();
- if (! result)
- break;
-
- arg_index = 0;
- expr = find_leaf(context, 1, arg_index);
- value_t moment;
- expr->compute(moment, details, context);
- if (moment.type == value_t::DATETIME) {
- result.cast(value_t::INTEGER);
- moment.cast(value_t::INTEGER);
- result -= moment;
- } else {
- throw new compute_error("Invalid date passed to datecmp(value,date)",
- new valexpr_context(expr));
- }
- break;
- }
-
- case F_YEAR:
- case F_MONTH:
- case F_DAY: {
- int arg_index = 0;
- value_expr_t * expr = find_leaf(context, 0, arg_index);
- expr->compute(result, details, context);
-
- if (result.type != value_t::DATETIME)
- throw new compute_error("Invalid date passed to year|month|day(date)",
- new valexpr_context(expr));
-
- datetime_t& moment(*((datetime_t *)result.data));
- switch (kind) {
- case F_YEAR:
- result = (long)moment.year();
- break;
- case F_MONTH:
- result = (long)moment.month();
- break;
- case F_DAY:
- result = (long)moment.day();
- break;
- }
- break;
- }
-
- case F_ARITH_MEAN: {
- int arg_index = 0;
- value_expr_t * expr = find_leaf(context, 0, arg_index);
- if (details.xact && transaction_has_xdata(*details.xact)) {
- expr->compute(result, details, context);
- result /= amount_t(long(transaction_xdata_(*details.xact).index + 1));
- }
- else if (details.account && account_has_xdata(*details.account) &&
- account_xdata(*details.account).total_count) {
- expr->compute(result, details, context);
- result /= amount_t(long(account_xdata(*details.account).total_count));
- }
- else {
- result = 0L;
- }
- break;
- }
-
- case F_PARENT:
- if (details.account && details.account->parent)
- left->compute(result, details_t(*details.account->parent), context);
- break;
-
- case F_ABS: {
- int arg_index = 0;
- value_expr_t * expr = find_leaf(context, 0, arg_index);
- expr->compute(result, details, context);
- result.abs();
- break;
- }
-
- case F_ROUND: {
- int arg_index = 0;
- value_expr_t * expr = find_leaf(context, 0, arg_index);
- expr->compute(result, details, context);
- result.round();
- break;
- }
-
- case F_COMMODITY: {
- int arg_index = 0;
- value_expr_t * expr = find_leaf(context, 0, arg_index);
- expr->compute(result, details, context);
- if (result.type != value_t::AMOUNT)
- throw new compute_error("Argument to commodity() must be a commoditized amount",
- new valexpr_context(expr));
- amount_t temp("1");
- temp.set_commodity(((amount_t *) result.data)->commodity());
- result = temp;
- break;
- }
-
- case F_SET_COMMODITY: {
- int arg_index = 0;
- value_expr_t * expr = find_leaf(context, 0, arg_index);
- value_t temp;
- expr->compute(temp, details, context);
-
- arg_index = 0;
- expr = find_leaf(context, 1, arg_index);
- expr->compute(result, details, context);
- if (result.type != value_t::AMOUNT)
- throw new compute_error
- ("Second argument to set_commodity() must be a commoditized amount",
- new valexpr_context(expr));
- amount_t one("1");
- one.set_commodity(((amount_t *) result.data)->commodity());
- result = one;
-
- result *= temp;
- break;
- }
-
- case F_QUANTITY: {
- int arg_index = 0;
- value_expr_t * expr = find_leaf(context, 0, arg_index);
- expr->compute(result, details, context);
-
- balance_t * bal = NULL;
- switch (result.type) {
- case value_t::BALANCE_PAIR:
- bal = &((balance_pair_t *) result.data)->quantity;
- // fall through...
-
- case value_t::BALANCE:
- if (! bal)
- bal = (balance_t *) result.data;
-
- if (bal->amounts.size() < 2) {
- result.cast(value_t::AMOUNT);
- } else {
- value_t temp;
- for (amounts_map::const_iterator i = bal->amounts.begin();
- i != bal->amounts.end();
- i++) {
- amount_t x = (*i).second;
- x.clear_commodity();
- temp += x;
- }
- result = temp;
- assert(temp.type == value_t::AMOUNT);
- }
- // fall through...
-
- case value_t::AMOUNT:
- ((amount_t *) result.data)->clear_commodity();
- break;
-
- default:
- break;
- }
- break;
- }
-
- case F_CODE_MASK:
- assert(mask);
- if (details.entry)
- result = mask->match(details.entry->code);
- else
- result = false;
- break;
-
- case F_PAYEE_MASK:
- assert(mask);
- if (details.entry)
- result = mask->match(details.entry->payee);
- else
- result = false;
- break;
-
- case F_NOTE_MASK:
- assert(mask);
- if (details.xact)
- result = mask->match(details.xact->note);
- else
- result = false;
- break;
-
- case F_ACCOUNT_MASK:
- assert(mask);
- if (details.account)
- result = mask->match(details.account->fullname());
- else
- result = false;
- break;
-
- case F_SHORT_ACCOUNT_MASK:
- assert(mask);
- if (details.account)
- result = mask->match(details.account->name);
- else
- result = false;
- break;
-
- case F_COMMODITY_MASK:
- assert(mask);
- if (details.xact)
- result = mask->match(details.xact->amount.commodity().base_symbol());
- else
- result = false;
- break;
-
- case O_ARG: {
- int arg_index = 0;
- assert(left);
- assert(left->kind == ARG_INDEX);
- value_expr_t * expr = find_leaf(context, left->arg_index, arg_index);
- if (expr)
- expr->compute(result, details, context);
- else
- result = 0L;
- break;
- }
-
- case O_COM:
- if (! left)
- throw new compute_error("Comma operator missing left operand",
- new valexpr_context(this));
- if (! right)
- throw new compute_error("Comma operator missing right operand",
- new valexpr_context(this));
- left->compute(result, details, context);
- right->compute(result, details, context);
- break;
-
- case O_DEF:
- result = 0L;
- break;
-
- case O_REF: {
- assert(left);
- if (right) {
- value_expr args(reduce_leaves(right, details, context));
- left->compute(result, details, args.get());
- } else {
- left->compute(result, details, context);
- }
- break;
- }
-
- case F_VALUE: {
- int arg_index = 0;
- value_expr_t * expr = find_leaf(context, 0, arg_index);
- expr->compute(result, details, context);
-
- arg_index = 0;
- expr = find_leaf(context, 1, arg_index);
- value_t moment;
- expr->compute(moment, details, context);
- if (moment.type != value_t::DATETIME)
- throw new compute_error("Invalid date passed to P(value,date)",
- new valexpr_context(expr));
-
- result = result.value(*((datetime_t *)moment.data));
- break;
- }
-
- case O_NOT:
- left->compute(result, details, context);
- if (result.strip_annotations())
- result = false;
- else
- result = true;
- break;
-
- case O_QUES: {
- assert(left);
- assert(right);
- assert(right->kind == O_COL);
- left->compute(result, details, context);
- if (result.strip_annotations())
- right->left->compute(result, details, context);
- else
- right->right->compute(result, details, context);
- break;
- }
-
- case O_AND:
- assert(left);
- assert(right);
- left->compute(result, details, context);
- result = result.strip_annotations();
- if (result)
- right->compute(result, details, context);
- break;
-
- case O_OR:
- assert(left);
- assert(right);
- left->compute(result, details, context);
- if (! result.strip_annotations())
- right->compute(result, details, context);
- break;
-
- case O_NEQ:
- case O_EQ:
- case O_LT:
- case O_LTE:
- case O_GT:
- case O_GTE: {
- assert(left);
- assert(right);
- value_t temp;
- left->compute(temp, details, context);
- right->compute(result, details, context);
- switch (kind) {
- case O_NEQ: result = temp != result; break;
- case O_EQ: result = temp == result; break;
- case O_LT: result = temp < result; break;
- case O_LTE: result = temp <= result; break;
- case O_GT: result = temp > result; break;
- case O_GTE: result = temp >= result; break;
- default: assert(0); break;
- }
- break;
- }
-
- case O_NEG:
- assert(left);
- left->compute(result, details, context);
- result.negate();
- break;
-
- case O_ADD:
- case O_SUB:
- case O_MUL:
- case O_DIV: {
- assert(left);
- assert(right);
- value_t temp;
- right->compute(temp, details, context);
- left->compute(result, details, context);
- switch (kind) {
- case O_ADD: result += temp; break;
- case O_SUB: result -= temp; break;
- case O_MUL: result *= temp; break;
- case O_DIV: result /= temp; break;
- default: assert(0); break;
- }
- break;
- }
-
- case O_PERC: {
- assert(left);
- result = "100.0%";
- value_t temp;
- left->compute(temp, details, context);
- result *= temp;
- break;
- }
-
- case LAST:
- default:
- assert(0);
- break;
- }
- }
- catch (error * err) {
- if (err->context.empty() ||
- ! dynamic_cast<valexpr_context *>(err->context.back()))
- err->context.push_back(new valexpr_context(this));
- throw err;
- }
-}
-
-static inline void unexpected(char c, char wanted = '\0') {
- if ((unsigned char) c == 0xff) {
- if (wanted)
- throw new value_expr_error(std::string("Missing '") + wanted + "'");
- else
- throw new value_expr_error("Unexpected end");
- } else {
- if (wanted)
- throw new value_expr_error(std::string("Invalid char '") + c +
- "' (wanted '" + wanted + "')");
- else
- throw new value_expr_error(std::string("Invalid char '") + c + "'");
- }
-}
-
-value_expr_t * parse_value_term(std::istream& in, scope_t * scope,
- const short flags);
-
-inline value_expr_t * parse_value_term(const char * p, scope_t * scope,
- const short flags) {
- std::istringstream stream(p);
- return parse_value_term(stream, scope, flags);
-}
-
-value_expr_t * parse_value_term(std::istream& in, scope_t * scope,
- const short flags)
-{
- value_expr node;
-
- char buf[256];
- char c = peek_next_nonws(in);
-
- if (flags & PARSE_VALEXPR_RELAXED) {
- if (c == '@') {
- in.get(c);
- c = peek_next_nonws(in);
- }
- else if (! (c == '(' || c == '[' || c == '{' || c == '/')) {
- amount_t temp;
- char prev_c = c;
- unsigned long pos = 0;
- // When in relaxed parsing mode, we do want to migrate commodity
- // flags, so that any precision specified by the user updates
- // the current maximum precision displayed.
- pos = (long)in.tellg();
-
- unsigned char parse_flags = 0;
- if (flags & PARSE_VALEXPR_NO_MIGRATE)
- parse_flags |= AMOUNT_PARSE_NO_MIGRATE;
- if (flags & PARSE_VALEXPR_NO_REDUCE)
- parse_flags |= AMOUNT_PARSE_NO_REDUCE;
-
- if (! temp.parse(in, parse_flags | AMOUNT_PARSE_SOFT_FAIL)) {
- in.clear();
- in.seekg(pos, std::ios::beg);
- c = prev_c;
- goto parse_ident;
- }
-
- node.reset(new value_expr_t(value_expr_t::CONSTANT));
- node->value = new value_t(temp);
- goto parsed;
- }
- }
-
- parse_ident:
- if (std::isdigit(c) || c == '.') {
- READ_INTO(in, buf, 255, c, std::isdigit(c) || c == '.');
- amount_t temp;
- temp.parse(buf, AMOUNT_PARSE_NO_MIGRATE);
- node.reset(new value_expr_t(value_expr_t::CONSTANT));
- node->value = new value_t(temp);
- goto parsed;
- }
- else if (std::isalnum(c) || c == '_') {
- bool have_args = false;
- istream_pos_type beg;
-
- READ_INTO(in, buf, 255, c, std::isalnum(c) || c == '_');
- c = peek_next_nonws(in);
- if (c == '(') {
- in.get(c);
- beg = in.tellg();
-
- int paren_depth = 0;
- while (! in.eof()) {
- in.get(c);
- if (c == '(' || c == '{' || c == '[')
- paren_depth++;
- else if (c == ')' || c == '}' || c == ']') {
- if (paren_depth == 0)
- break;
- paren_depth--;
- }
- }
- if (c != ')')
- unexpected(c, ')');
-
- have_args = true;
- c = peek_next_nonws(in);
- }
-
- bool definition = false;
- if (c == '=') {
- in.get(c);
- if (peek_next_nonws(in) == '=') {
- in.unget();
- c = '\0';
- } else {
- definition = true;
- }
- }
-
- if (definition) {
- std::auto_ptr<scope_t> params(new scope_t(scope));
-
- int arg_index = 0;
- if (have_args) {
- bool done = false;
-
- in.clear();
- in.seekg(beg, std::ios::beg);
- while (! done && ! in.eof()) {
- char ident[32];
- READ_INTO(in, ident, 31, c, std::isalnum(c) || c == '_');
-
- c = peek_next_nonws(in);
- in.get(c);
- if (c != ',' && c != ')')
- unexpected(c, ')');
- else if (c == ')')
- done = true;
-
- // Define the parameter so that on lookup the parser will find
- // an O_ARG value.
- node.reset(new value_expr_t(value_expr_t::O_ARG));
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = arg_index++;
- params->define(ident, node.release());
- }
-
- if (peek_next_nonws(in) != '=') {
- in.get(c);
- unexpected(c, '=');
- }
- in.get(c);
- }
-
- // Define the value associated with the defined identifier
- value_expr def(parse_boolean_expr(in, params.get(), flags));
- if (! def.get())
- throw new value_expr_error(std::string("Definition failed for '") + buf + "'");
-
- node.reset(new value_expr_t(value_expr_t::O_DEF));
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = arg_index;
- node->set_right(def.release());
-
- scope->define(buf, node.get());
- } else {
- assert(scope);
- value_expr_t * def = scope->lookup(buf);
- if (! def) {
- if (buf[1] == '\0' &&
- (buf[0] == 'c' || buf[0] == 'C' || buf[0] == 'p' ||
- buf[0] == 'w' || buf[0] == 'W' || buf[0] == 'e')) {
- in.unget();
- goto find_term;
- }
- throw new value_expr_error(std::string("Unknown identifier '") +
- buf + "'");
- }
- else if (def->kind == value_expr_t::O_DEF) {
- node.reset(new value_expr_t(value_expr_t::O_REF));
- node->set_left(def->right);
-
- int count = 0;
- if (have_args) {
- in.clear();
- in.seekg(beg, std::ios::beg);
- value_expr args
- (parse_value_expr(in, scope, flags | PARSE_VALEXPR_PARTIAL));
-
- if (peek_next_nonws(in) != ')') {
- in.get(c);
- unexpected(c, ')');
- }
- in.get(c);
-
- if (args.get()) {
- count = count_leaves(args.get());
- node->set_right(args.release());
- }
- }
-
- if (count != def->left->arg_index) {
- std::ostringstream errmsg;
- errmsg << "Wrong number of arguments to '" << buf
- << "': saw " << count << ", wanted " << def->left->arg_index;
- throw new value_expr_error(errmsg.str());
- }
- }
- else {
- node.reset(def);
- }
- }
- goto parsed;
- }
-
- find_term:
- in.get(c);
- switch (c) {
- // Functions
- case '^':
- node.reset(new value_expr_t(value_expr_t::F_PARENT));
- node->set_left(parse_value_term(in, scope, flags));
- break;
-
- // Other
- case 'c':
- case 'C':
- case 'p':
- case 'w':
- case 'W':
- case 'e':
- case '/': {
- bool code_mask = c == 'c';
- bool commodity_mask = c == 'C';
- bool payee_mask = c == 'p';
- bool note_mask = c == 'e';
- bool short_account_mask = c == 'w';
-
- if (c == '/') {
- c = peek_next_nonws(in);
- if (c == '/') {
- in.get(c);
- c = in.peek();
- if (c == '/') {
- in.get(c);
- c = in.peek();
- short_account_mask = true;
- } else {
- payee_mask = true;
- }
- }
- } else {
- in.get(c);
- }
-
- // Read in the regexp
- READ_INTO(in, buf, 255, c, c != '/');
- if (c != '/')
- unexpected(c, '/');
-
- value_expr_t::kind_t kind;
-
- if (short_account_mask)
- kind = value_expr_t::F_SHORT_ACCOUNT_MASK;
- else if (code_mask)
- kind = value_expr_t::F_CODE_MASK;
- else if (commodity_mask)
- kind = value_expr_t::F_COMMODITY_MASK;
- else if (payee_mask)
- kind = value_expr_t::F_PAYEE_MASK;
- else if (note_mask)
- kind = value_expr_t::F_NOTE_MASK;
- else
- kind = value_expr_t::F_ACCOUNT_MASK;
-
- in.get(c);
- node.reset(new value_expr_t(kind));
- node->mask = new mask_t(buf);
- break;
- }
-
- case '{': {
- amount_t temp;
- temp.parse(in, AMOUNT_PARSE_NO_MIGRATE);
- in.get(c);
- if (c != '}')
- unexpected(c, '}');
-
- node.reset(new value_expr_t(value_expr_t::CONSTANT));
- node->value = new value_t(temp);
- break;
- }
-
- case '(': {
- std::auto_ptr<scope_t> locals(new scope_t(scope));
- node.reset(parse_value_expr(in, locals.get(),
- flags | PARSE_VALEXPR_PARTIAL));
- in.get(c);
- if (c != ')')
- unexpected(c, ')');
- break;
- }
-
- case '[': {
- READ_INTO(in, buf, 255, c, c != ']');
- if (c != ']')
- unexpected(c, ']');
- in.get(c);
-
- interval_t timespan(buf);
- node.reset(new value_expr_t(value_expr_t::CONSTANT));
- node->value = new value_t(timespan.first());
- break;
- }
-
- default:
- in.unget();
- break;
- }
-
- parsed:
- return node.release();
-}
-
-value_expr_t * parse_mul_expr(std::istream& in, scope_t * scope,
- const short flags)
-{
- value_expr node;
-
- if (peek_next_nonws(in) == '%') {
- char c;
- in.get(c);
- node.reset(new value_expr_t(value_expr_t::O_PERC));
- node->set_left(parse_value_term(in, scope, flags));
- return node.release();
- }
-
- node.reset(parse_value_term(in, scope, flags));
-
- if (node.get() && ! in.eof()) {
- char c = peek_next_nonws(in);
- while (c == '*' || c == '/') {
- in.get(c);
- switch (c) {
- case '*': {
- value_expr prev(node.release());
- node.reset(new value_expr_t(value_expr_t::O_MUL));
- node->set_left(prev.release());
- node->set_right(parse_value_term(in, scope, flags));
- break;
- }
-
- case '/': {
- value_expr prev(node.release());
- node.reset(new value_expr_t(value_expr_t::O_DIV));
- node->set_left(prev.release());
- node->set_right(parse_value_term(in, scope, flags));
- break;
- }
- }
- c = peek_next_nonws(in);
- }
- }
-
- return node.release();
-}
-
-value_expr_t * parse_add_expr(std::istream& in, scope_t * scope,
- const short flags)
-{
- value_expr node;
-
- if (peek_next_nonws(in) == '-') {
- char c;
- in.get(c);
- value_expr expr(parse_mul_expr(in, scope, flags));
- if (expr->kind == value_expr_t::CONSTANT) {
- expr->value->negate();
- return expr.release();
- }
- node.reset(new value_expr_t(value_expr_t::O_NEG));
- node->set_left(expr.release());
- return node.release();
- }
-
- node.reset(parse_mul_expr(in, scope, flags));
-
- if (node.get() && ! in.eof()) {
- char c = peek_next_nonws(in);
- while (c == '+' || c == '-') {
- in.get(c);
- switch (c) {
- case '+': {
- value_expr prev(node.release());
- node.reset(new value_expr_t(value_expr_t::O_ADD));
- node->set_left(prev.release());
- node->set_right(parse_mul_expr(in, scope, flags));
- break;
- }
-
- case '-': {
- value_expr prev(node.release());
- node.reset(new value_expr_t(value_expr_t::O_SUB));
- node->set_left(prev.release());
- node->set_right(parse_mul_expr(in, scope, flags));
- break;
- }
- }
- c = peek_next_nonws(in);
- }
- }
-
- return node.release();
-}
-
-value_expr_t * parse_logic_expr(std::istream& in, scope_t * scope,
- const short flags)
-{
- value_expr node;
-
- if (peek_next_nonws(in) == '!') {
- char c;
- in.get(c);
- node.reset(new value_expr_t(value_expr_t::O_NOT));
- node->set_left(parse_add_expr(in, scope, flags));
- return node.release();
- }
-
- node.reset(parse_add_expr(in, scope, flags));
-
- if (node.get() && ! in.eof()) {
- char c = peek_next_nonws(in);
- if (c == '!' || c == '=' || c == '<' || c == '>') {
- in.get(c);
- switch (c) {
- case '!':
- case '=': {
- bool negate = c == '!';
- if ((c = peek_next_nonws(in)) == '=')
- in.get(c);
- else
- unexpected(c, '=');
- value_expr prev(node.release());
- node.reset(new value_expr_t(negate ? value_expr_t::O_NEQ :
- value_expr_t::O_EQ));
- node->set_left(prev.release());
- node->set_right(parse_add_expr(in, scope, flags));
- break;
- }
-
- case '<': {
- value_expr prev(node.release());
- node.reset(new value_expr_t(value_expr_t::O_LT));
- if (peek_next_nonws(in) == '=') {
- in.get(c);
- node->kind = value_expr_t::O_LTE;
- }
- node->set_left(prev.release());
- node->set_right(parse_add_expr(in, scope, flags));
- break;
- }
-
- case '>': {
- value_expr prev(node.release());
- node.reset(new value_expr_t(value_expr_t::O_GT));
- if (peek_next_nonws(in) == '=') {
- in.get(c);
- node->kind = value_expr_t::O_GTE;
- }
- node->set_left(prev.release());
- node->set_right(parse_add_expr(in, scope, flags));
- break;
- }
-
- default:
- if (! in.eof())
- unexpected(c);
- break;
- }
- }
- }
-
- return node.release();
-}
-
-value_expr_t * parse_boolean_expr(std::istream& in, scope_t * scope,
- const short flags)
-{
- value_expr node(parse_logic_expr(in, scope, flags));
-
- if (node.get() && ! in.eof()) {
- char c = peek_next_nonws(in);
- while (c == '&' || c == '|' || c == '?') {
- in.get(c);
- switch (c) {
- case '&': {
- value_expr prev(node.release());
- node.reset(new value_expr_t(value_expr_t::O_AND));
- node->set_left(prev.release());
- node->set_right(parse_logic_expr(in, scope, flags));
- break;
- }
-
- case '|': {
- value_expr prev(node.release());
- node.reset(new value_expr_t(value_expr_t::O_OR));
- node->set_left(prev.release());
- node->set_right(parse_logic_expr(in, scope, flags));
- break;
- }
-
- case '?': {
- value_expr prev(node.release());
- node.reset(new value_expr_t(value_expr_t::O_QUES));
- node->set_left(prev.release());
- node->set_right(new value_expr_t(value_expr_t::O_COL));
- node->right->set_left(parse_logic_expr(in, scope, flags));
- c = peek_next_nonws(in);
- if (c != ':')
- unexpected(c, ':');
- in.get(c);
- node->right->set_right(parse_logic_expr(in, scope, flags));
- break;
- }
-
- default:
- if (! in.eof())
- unexpected(c);
- break;
- }
- c = peek_next_nonws(in);
- }
- }
-
- return node.release();
-}
-
-void init_value_expr()
-{
- global_scope.reset(new scope_t());
- scope_t * globals = global_scope.get();
-
- value_expr_t * node;
-
- // Basic terms
- node = new value_expr_t(value_expr_t::F_NOW);
- globals->define("m", node);
- globals->define("now", node);
- globals->define("today", node);
-
- node = new value_expr_t(value_expr_t::AMOUNT);
- globals->define("a", node);
- globals->define("amount", node);
-
- node = new value_expr_t(value_expr_t::PRICE);
- globals->define("i", node);
- globals->define("price", node);
-
- node = new value_expr_t(value_expr_t::COST);
- globals->define("b", node);
- globals->define("cost", node);
-
- node = new value_expr_t(value_expr_t::DATE);
- globals->define("d", node);
- globals->define("date", node);
-
- node = new value_expr_t(value_expr_t::ACT_DATE);
- globals->define("act_date", node);
- globals->define("actual_date", node);
-
- node = new value_expr_t(value_expr_t::EFF_DATE);
- globals->define("eff_date", node);
- globals->define("effective_date", node);
-
- node = new value_expr_t(value_expr_t::CLEARED);
- globals->define("X", node);
- globals->define("cleared", node);
-
- node = new value_expr_t(value_expr_t::PENDING);
- globals->define("Y", node);
- globals->define("pending", node);
-
- node = new value_expr_t(value_expr_t::REAL);
- globals->define("R", node);
- globals->define("real", node);
-
- node = new value_expr_t(value_expr_t::ACTUAL);
- globals->define("L", node);
- globals->define("actual", node);
-
- node = new value_expr_t(value_expr_t::INDEX);
- globals->define("n", node);
- globals->define("index", node);
-
- node = new value_expr_t(value_expr_t::COUNT);
- globals->define("N", node);
- globals->define("count", node);
-
- node = new value_expr_t(value_expr_t::DEPTH);
- globals->define("l", node);
- globals->define("depth", node);
-
- node = new value_expr_t(value_expr_t::TOTAL);
- globals->define("O", node);
- globals->define("total", node);
-
- node = new value_expr_t(value_expr_t::PRICE_TOTAL);
- globals->define("I", node);
- globals->define("total_price", node);
-
- node = new value_expr_t(value_expr_t::COST_TOTAL);
- globals->define("B", node);
- globals->define("total_cost", node);
-
- // Relating to format_t
- globals->define("t", new value_expr_t(value_expr_t::VALUE_EXPR));
- globals->define("T", new value_expr_t(value_expr_t::TOTAL_EXPR));
-
- // Functions
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 1;
- node->set_right(new value_expr_t(value_expr_t::F_ABS));
- globals->define("U", node);
- globals->define("abs", node);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 1;
- node->set_right(new value_expr_t(value_expr_t::F_ROUND));
- globals->define("round", node);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 1;
- node->set_right(new value_expr_t(value_expr_t::F_QUANTITY));
- globals->define("S", node);
- globals->define("quant", node);
- globals->define("quantity", node);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 1;
- node->set_right(new value_expr_t(value_expr_t::F_COMMODITY));
- globals->define("comm", node);
- globals->define("commodity", node);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 2;
- node->set_right(new value_expr_t(value_expr_t::F_SET_COMMODITY));
- globals->define("setcomm", node);
- globals->define("set_commodity", node);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 1;
- node->set_right(new value_expr_t(value_expr_t::F_ARITH_MEAN));
- globals->define("A", node);
- globals->define("avg", node);
- globals->define("mean", node);
- globals->define("average", node);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 2;
- node->set_right(new value_expr_t(value_expr_t::F_VALUE));
- globals->define("P", node);
-
- parse_value_definition("@value=@P(@t,@m)", globals);
- parse_value_definition("@total_value=@P(@T,@m)", globals);
- parse_value_definition("@valueof(x)=@P(@x,@m)", globals);
- parse_value_definition("@datedvalueof(x,y)=@P(@x,@y)", globals);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 1;
- node->set_right(new value_expr_t(value_expr_t::F_PRICE));
- globals->define("priceof", node);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 1;
- node->set_right(new value_expr_t(value_expr_t::F_DATE));
- globals->define("dateof", node);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 2;
- node->set_right(new value_expr_t(value_expr_t::F_DATECMP));
- globals->define("datecmp", node);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 1;
- node->set_right(new value_expr_t(value_expr_t::F_YEAR));
- globals->define("yearof", node);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 1;
- node->set_right(new value_expr_t(value_expr_t::F_MONTH));
- globals->define("monthof", node);
-
- node = new value_expr_t(value_expr_t::O_DEF);
- node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
- node->left->arg_index = 1;
- node->set_right(new value_expr_t(value_expr_t::F_DAY));
- globals->define("dayof", node);
-
- parse_value_definition("@year=@yearof(@d)", globals);
- parse_value_definition("@month=@monthof(@d)", globals);
- parse_value_definition("@day=@dayof(@d)", globals);
-
- // Macros
- node = parse_value_expr("@P(@a,@d)");
- globals->define("v", node);
- globals->define("market", node);
-
- node = parse_value_expr("@P(@O,@d)");
- globals->define("V", node);
- globals->define("total_market", node);
-
- node = parse_value_expr("@v-@b");
- globals->define("g", node);
- globals->define("gain", node);
-
- node = parse_value_expr("@V-@B");
- globals->define("G", node);
- globals->define("total_gain", node);
-
- parse_value_definition("@min(x,y)=@x<@y?@x:@y", globals);
- parse_value_definition("@max(x,y)=@x>@y?@x:@y", globals);
-}
-
-value_expr_t * parse_value_expr(std::istream& in, scope_t * scope,
- const short flags)
-{
- if (! global_scope.get())
- init_value_expr();
-
- std::auto_ptr<scope_t> this_scope(new scope_t(scope ? scope :
- global_scope.get()));
- value_expr node;
- node.reset(parse_boolean_expr(in, this_scope.get(), flags));
-
- if (node.get() && ! in.eof()) {
- char c = peek_next_nonws(in);
- while (c == ',') {
- in.get(c);
- switch (c) {
- case ',': {
- value_expr prev(node.release());
- node.reset(new value_expr_t(value_expr_t::O_COM));
- node->set_left(prev.release());
- node->set_right(parse_logic_expr(in, this_scope.get(), flags));
- break;
- }
-
- default:
- if (! in.eof())
- unexpected(c);
- break;
- }
- c = peek_next_nonws(in);
- }
- }
-
- char c;
- if (! node.get()) {
- in.get(c);
- if (in.eof())
- throw new value_expr_error(std::string("Failed to parse value expression"));
- else
- unexpected(c);
- } else if (! (flags & PARSE_VALEXPR_PARTIAL)) {
- in.get(c);
- if (! in.eof())
- unexpected(c);
- else
- in.unget();
- }
-
- return node.release();
-}
-
-valexpr_context::valexpr_context(const ledger::value_expr_t * _expr,
- const std::string& desc) throw()
- : expr(_expr), error_node(_expr), error_context(desc)
-{
- error_node->acquire();
-}
-
-valexpr_context::~valexpr_context() throw()
-{
- if (expr) expr->release();
- if (error_node) error_node->release();
-}
-
-void valexpr_context::describe(std::ostream& out) const throw()
-{
- if (! expr) {
- out << "valexpr_context expr not set!" << std::endl;
- return;
- }
-
- if (! desc.empty())
- out << desc << std::endl;
-
- out << " ";
- unsigned long start = (long)out.tellp() - 1;
- unsigned long begin;
- unsigned long end;
- bool found = ledger::write_value_expr(out, expr, true,
- error_node, &begin, &end);
- out << std::endl;
- if (found) {
- out << " ";
- for (int i = 0; i < end - start; i++) {
- if (i >= begin - start)
- out << "^";
- else
- out << " ";
- }
- out << std::endl;
- }
-}
-
-bool write_value_expr(std::ostream& out,
- const value_expr_t * node,
- const bool relaxed,
- const value_expr_t * node_to_find,
- unsigned long * start_pos,
- unsigned long * end_pos)
-{
- int arg_index = 0;
- bool found = false;
- value_expr_t * expr;
-
- if (start_pos && node == node_to_find) {
- *start_pos = (long)out.tellp() - 1;
- found = true;
- }
-
- std::string symbol;
-
- switch (node->kind) {
- case value_expr_t::ARG_INDEX:
- out << node->arg_index;
- break;
-
- case value_expr_t::CONSTANT:
- switch (node->value->type) {
- case value_t::BOOLEAN:
- assert(0);
- break;
- case value_t::DATETIME:
- out << '[' << *(node->value) << ']';
- break;
- case value_t::INTEGER:
- case value_t::AMOUNT:
- if (! relaxed)
- out << '{';
- out << *(node->value);
- if (! relaxed)
- out << '}';
- break;
- case value_t::BALANCE:
- case value_t::BALANCE_PAIR:
- assert(0);
- break;
- }
- break;
-
- case value_expr_t::AMOUNT:
- symbol = "amount"; break;
- case value_expr_t::PRICE:
- symbol = "price"; break;
- case value_expr_t::COST:
- symbol = "cost"; break;
- case value_expr_t::DATE:
- symbol = "date"; break;
- case value_expr_t::ACT_DATE:
- symbol = "actual_date"; break;
- case value_expr_t::EFF_DATE:
- symbol = "effective_date"; break;
- case value_expr_t::CLEARED:
- symbol = "cleared"; break;
- case value_expr_t::PENDING:
- symbol = "pending"; break;
- case value_expr_t::REAL:
- symbol = "real"; break;
- case value_expr_t::ACTUAL:
- symbol = "actual"; break;
- case value_expr_t::INDEX:
- symbol = "index"; break;
- case value_expr_t::COUNT:
- symbol = "count"; break;
- case value_expr_t::DEPTH:
- symbol = "depth"; break;
- case value_expr_t::TOTAL:
- symbol = "total"; break;
- case value_expr_t::PRICE_TOTAL:
- symbol = "total_price"; break;
- case value_expr_t::COST_TOTAL:
- symbol = "total_cost"; break;
- case value_expr_t::F_NOW:
- symbol = "now"; break;
-
- case value_expr_t::VALUE_EXPR:
- if (write_value_expr(out, amount_expr.get(), relaxed,
- node_to_find, start_pos, end_pos))
- found = true;
- break;
- case value_expr_t::TOTAL_EXPR:
- if (write_value_expr(out, total_expr.get(), relaxed,
- node_to_find, start_pos, end_pos))
- found = true;
- break;
-
- case value_expr_t::F_ARITH_MEAN:
- symbol = "average"; break;
- case value_expr_t::F_ABS:
- symbol = "abs"; break;
- case value_expr_t::F_QUANTITY:
- symbol = "quantity"; break;
- case value_expr_t::F_COMMODITY:
- symbol = "commodity"; break;
- case value_expr_t::F_SET_COMMODITY:
- symbol = "set_commodity"; break;
- case value_expr_t::F_VALUE:
- symbol = "valueof"; break;
- case value_expr_t::F_PRICE:
- symbol = "priceof"; break;
- case value_expr_t::F_DATE:
- symbol = "dateof"; break;
- case value_expr_t::F_DATECMP:
- symbol = "datecmp"; break;
- case value_expr_t::F_YEAR:
- symbol = "yearof"; break;
- case value_expr_t::F_MONTH:
- symbol = "monthof"; break;
- case value_expr_t::F_DAY:
- symbol = "dayof"; break;
-
- case value_expr_t::F_CODE_MASK:
- out << "c/" << node->mask->pattern << "/";
- break;
- case value_expr_t::F_PAYEE_MASK:
- out << "p/" << node->mask->pattern << "/";
- break;
- case value_expr_t::F_NOTE_MASK:
- out << "e/" << node->mask->pattern << "/";
- break;
- case value_expr_t::F_ACCOUNT_MASK:
- out << "W/" << node->mask->pattern << "/";
- break;
- case value_expr_t::F_SHORT_ACCOUNT_MASK:
- out << "w/" << node->mask->pattern << "/";
- break;
- case value_expr_t::F_COMMODITY_MASK:
- out << "C/" << node->mask->pattern << "/";
- break;
-
- case value_expr_t::O_NOT:
- out << "!";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- break;
- case value_expr_t::O_NEG:
- out << "-";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- break;
- case value_expr_t::O_PERC:
- out << "%";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- break;
-
- case value_expr_t::O_ARG:
- out << "@arg" << node->arg_index;
- break;
- case value_expr_t::O_DEF:
- out << "<def args=\"";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << "\" value=\"";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << "\">";
- break;
-
- case value_expr_t::O_REF:
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- if (node->right) {
- out << "(";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- }
- break;
-
- case value_expr_t::O_COM:
- if (node->left &&
- write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ", ";
- if (node->right &&
- write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- break;
- case value_expr_t::O_QUES:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " ? ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
- case value_expr_t::O_COL:
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " : ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- break;
-
- case value_expr_t::O_AND:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " & ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
- case value_expr_t::O_OR:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " | ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
-
- case value_expr_t::O_NEQ:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " != ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
- case value_expr_t::O_EQ:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " == ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
- case value_expr_t::O_LT:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " < ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
- case value_expr_t::O_LTE:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " <= ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
- case value_expr_t::O_GT:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " > ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
- case value_expr_t::O_GTE:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " >= ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
-
- case value_expr_t::O_ADD:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " + ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
- case value_expr_t::O_SUB:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " - ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
- case value_expr_t::O_MUL:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " * ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
- case value_expr_t::O_DIV:
- out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << " / ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
- found = true;
- out << ")";
- break;
-
- case value_expr_t::LAST:
- default:
- assert(0);
- break;
- }
-
- if (! symbol.empty()) {
- if (commodity_t::find(symbol))
- out << '@';
- out << symbol;
- }
-
- if (end_pos && node == node_to_find)
- *end_pos = (long)out.tellp() - 1;
-
- return found;
-}
-
-void dump_value_expr(std::ostream& out, const value_expr_t * node,
- const int depth)
-{
- out.setf(std::ios::left);
- out.width(10);
- out << node << " ";
-
- for (int i = 0; i < depth; i++)
- out << " ";
-
- switch (node->kind) {
- case value_expr_t::ARG_INDEX:
- out << "ARG_INDEX - " << node->arg_index;
- break;
- case value_expr_t::CONSTANT:
- out << "CONSTANT - " << *(node->value);
- break;
-
- case value_expr_t::AMOUNT: out << "AMOUNT"; break;
- case value_expr_t::PRICE: out << "PRICE"; break;
- case value_expr_t::COST: out << "COST"; break;
- case value_expr_t::DATE: out << "DATE"; break;
- case value_expr_t::ACT_DATE: out << "ACT_DATE"; break;
- case value_expr_t::EFF_DATE: out << "EFF_DATE"; break;
- case value_expr_t::CLEARED: out << "CLEARED"; break;
- case value_expr_t::PENDING: out << "PENDING"; break;
- case value_expr_t::REAL: out << "REAL"; break;
- case value_expr_t::ACTUAL: out << "ACTUAL"; break;
- case value_expr_t::INDEX: out << "INDEX"; break;
- case value_expr_t::COUNT: out << "COUNT"; break;
- case value_expr_t::DEPTH: out << "DEPTH"; break;
- case value_expr_t::TOTAL: out << "TOTAL"; break;
- case value_expr_t::PRICE_TOTAL: out << "PRICE_TOTAL"; break;
- case value_expr_t::COST_TOTAL: out << "COST_TOTAL"; break;
-
- case value_expr_t::VALUE_EXPR: out << "VALUE_EXPR"; break;
- case value_expr_t::TOTAL_EXPR: out << "TOTAL_EXPR"; break;
-
- case value_expr_t::F_NOW: out << "F_NOW"; break;
- case value_expr_t::F_ARITH_MEAN: out << "F_ARITH_MEAN"; break;
- case value_expr_t::F_ABS: out << "F_ABS"; break;
- case value_expr_t::F_QUANTITY: out << "F_QUANTITY"; break;
- case value_expr_t::F_COMMODITY: out << "F_COMMODITY"; break;
- case value_expr_t::F_SET_COMMODITY: out << "F_SET_COMMODITY"; break;
- case value_expr_t::F_CODE_MASK: out << "F_CODE_MASK"; break;
- case value_expr_t::F_PAYEE_MASK: out << "F_PAYEE_MASK"; break;
- case value_expr_t::F_NOTE_MASK: out << "F_NOTE_MASK"; break;
- case value_expr_t::F_ACCOUNT_MASK:
- out << "F_ACCOUNT_MASK"; break;
- case value_expr_t::F_SHORT_ACCOUNT_MASK:
- out << "F_SHORT_ACCOUNT_MASK"; break;
- case value_expr_t::F_COMMODITY_MASK:
- out << "F_COMMODITY_MASK"; break;
- case value_expr_t::F_VALUE: out << "F_VALUE"; break;
- case value_expr_t::F_PRICE: out << "F_PRICE"; break;
- case value_expr_t::F_DATE: out << "F_DATE"; break;
- case value_expr_t::F_DATECMP: out << "F_DATECMP"; break;
- case value_expr_t::F_YEAR: out << "F_YEAR"; break;
- case value_expr_t::F_MONTH: out << "F_MONTH"; break;
- case value_expr_t::F_DAY: out << "F_DAY"; break;
-
- case value_expr_t::O_NOT: out << "O_NOT"; break;
- case value_expr_t::O_ARG: out << "O_ARG"; break;
- case value_expr_t::O_DEF: out << "O_DEF"; break;
- case value_expr_t::O_REF: out << "O_REF"; break;
- case value_expr_t::O_COM: out << "O_COM"; break;
- case value_expr_t::O_QUES: out << "O_QUES"; break;
- case value_expr_t::O_COL: out << "O_COL"; break;
- case value_expr_t::O_AND: out << "O_AND"; break;
- case value_expr_t::O_OR: out << "O_OR"; break;
- case value_expr_t::O_NEQ: out << "O_NEQ"; break;
- case value_expr_t::O_EQ: out << "O_EQ"; break;
- case value_expr_t::O_LT: out << "O_LT"; break;
- case value_expr_t::O_LTE: out << "O_LTE"; break;
- case value_expr_t::O_GT: out << "O_GT"; break;
- case value_expr_t::O_GTE: out << "O_GTE"; break;
- case value_expr_t::O_NEG: out << "O_NEG"; break;
- case value_expr_t::O_ADD: out << "O_ADD"; break;
- case value_expr_t::O_SUB: out << "O_SUB"; break;
- case value_expr_t::O_MUL: out << "O_MUL"; break;
- case value_expr_t::O_DIV: out << "O_DIV"; break;
- case value_expr_t::O_PERC: out << "O_PERC"; break;
-
- case value_expr_t::LAST:
- default:
- assert(0);
- break;
- }
-
- out << " (" << node->refc << ')' << std::endl;
-
- if (node->kind > value_expr_t::TERMINALS) {
- if (node->left) {
- dump_value_expr(out, node->left, depth + 1);
- if (node->right)
- dump_value_expr(out, node->right, depth + 1);
- } else {
- assert(! node->right);
- }
- } else {
- assert(! node->left);
- }
-}
-
-} // namespace ledger
diff --git a/valexpr.h b/valexpr.h
deleted file mode 100644
index f0c1ed24..00000000
--- a/valexpr.h
+++ /dev/null
@@ -1,517 +0,0 @@
-#ifndef _VALEXPR_H
-#define _VALEXPR_H
-
-#include "value.h"
-#include "error.h"
-#include "mask.h"
-
-#include <memory>
-
-namespace ledger {
-
-class entry_t;
-class transaction_t;
-class account_t;
-
-struct details_t
-{
- const entry_t * entry;
- const transaction_t * xact;
- const account_t * account;
-
- details_t() : entry(NULL), xact(NULL), account(NULL) {}
- details_t(const entry_t& _entry)
- : entry(&_entry), xact(NULL), account(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor details_t");
- }
- details_t(const transaction_t& _xact);
- details_t(const account_t& _account)
- : entry(NULL), xact(NULL), account(&_account) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor details_t");
- }
-#ifdef DEBUG_ENABLED
- ~details_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor details_t");
- }
-#endif
-};
-
-struct value_expr_t
-{
- enum kind_t {
- // Constants
- CONSTANT,
- ARG_INDEX,
-
- CONSTANTS,
-
- // Item details
- AMOUNT,
- COST,
- PRICE,
- DATE,
- ACT_DATE,
- EFF_DATE,
- CLEARED,
- PENDING,
- REAL,
- ACTUAL,
- INDEX,
- DEPTH,
-
- // Item totals
- COUNT,
- TOTAL,
- COST_TOTAL,
- PRICE_TOTAL,
-
- // Relating to format_t
- VALUE_EXPR,
- TOTAL_EXPR,
-
- // Functions
- F_NOW,
- F_ARITH_MEAN,
- F_QUANTITY,
- F_COMMODITY,
- F_SET_COMMODITY,
- F_VALUE,
- F_ABS,
- F_ROUND,
- F_PRICE,
- F_DATE,
- F_DATECMP,
- F_YEAR,
- F_MONTH,
- F_DAY,
- F_CODE_MASK,
- F_PAYEE_MASK,
- F_NOTE_MASK,
- F_ACCOUNT_MASK,
- F_SHORT_ACCOUNT_MASK,
- F_COMMODITY_MASK,
-
- TERMINALS,
-
- F_PARENT,
-
- // Binary operators
- O_NEG,
- O_ADD,
- O_SUB,
- O_MUL,
- O_DIV,
- O_PERC,
- O_NEQ,
- O_EQ,
- O_LT,
- O_LTE,
- O_GT,
- O_GTE,
- O_NOT,
- O_AND,
- O_OR,
- O_QUES,
- O_COL,
- O_COM,
- O_DEF,
- O_REF,
- O_ARG,
-
- LAST
- };
-
- kind_t kind;
- mutable short refc;
- value_expr_t * left;
-
- union {
- value_t * value;
- mask_t * mask;
- unsigned int arg_index; // used by ARG_INDEX and O_ARG
- value_expr_t * right;
- };
-
- value_expr_t(const kind_t _kind)
- : kind(_kind), refc(0), left(NULL), right(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr_t " << this);
- }
- ~value_expr_t();
-
- void release() const {
- DEBUG_PRINT("ledger.valexpr.memory",
- "Releasing " << this << ", refc now " << refc - 1);
- assert(refc > 0);
- if (--refc == 0)
- delete this;
- }
- value_expr_t * acquire() {
- DEBUG_PRINT("ledger.valexpr.memory",
- "Acquiring " << this << ", refc now " << refc + 1);
- assert(refc >= 0);
- refc++;
- return this;
- }
- const value_expr_t * acquire() const {
- DEBUG_PRINT("ledger.valexpr.memory",
- "Acquiring " << this << ", refc now " << refc + 1);
- refc++;
- return this;
- }
-
- void set_left(value_expr_t * expr) {
- assert(kind > TERMINALS);
- if (left)
- left->release();
- left = expr ? expr->acquire() : NULL;
- }
-
- void set_right(value_expr_t * expr) {
- assert(kind > TERMINALS);
- if (right)
- right->release();
- right = expr ? expr->acquire() : NULL;
- }
-
- void compute(value_t& result,
- const details_t& details = details_t(),
- value_expr_t * context = NULL) const;
-
- value_t compute(const details_t& details = details_t(),
- value_expr_t * context = NULL) const {
- value_t temp;
- compute(temp, details, context);
- return temp;
- }
-
- private:
- value_expr_t(const value_expr_t&) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr_t (copy) " << this);
- }
-};
-
-class valexpr_context : public error_context {
- public:
- const ledger::value_expr_t * expr;
- const ledger::value_expr_t * error_node;
-
- valexpr_context(const ledger::value_expr_t * _expr,
- const std::string& desc = "") throw();
- virtual ~valexpr_context() throw();
-
- virtual void describe(std::ostream& out) const throw();
-};
-
-class compute_error : public error {
- public:
- compute_error(const std::string& reason, error_context * ctxt = NULL) throw()
- : error(reason, ctxt) {}
- virtual ~compute_error() throw() {}
-};
-
-class value_expr_error : public error {
- public:
- value_expr_error(const std::string& reason,
- error_context * ctxt = NULL) throw()
- : error(reason, ctxt) {}
- virtual ~value_expr_error() throw() {}
-};
-
-struct scope_t
-{
- scope_t * parent;
-
- typedef std::map<const std::string, value_expr_t *> symbol_map;
- typedef std::pair<const std::string, value_expr_t *> symbol_pair;
-
- symbol_map symbols;
-
- scope_t(scope_t * _parent = NULL) : parent(_parent) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor scope_t");
- }
- ~scope_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor scope_t");
- for (symbol_map::iterator i = symbols.begin();
- i != symbols.end();
- i++)
- (*i).second->release();
- }
-
- void define(const std::string& name, value_expr_t * def) {
- DEBUG_PRINT("ledger.valexpr.syms",
- "Defining '" << name << "' = " << def);
- std::pair<symbol_map::iterator, bool> result
- = symbols.insert(symbol_pair(name, def));
- if (! result.second) {
- symbols.erase(name);
- std::pair<symbol_map::iterator, bool> result
- = symbols.insert(symbol_pair(name, def));
- if (! result.second) {
- def->release();
- throw new compute_error(std::string("Redefinition of '") +
- name + "' in same scope");
- }
- }
- def->acquire();
- }
- value_expr_t * lookup(const std::string& name) {
- symbol_map::const_iterator i = symbols.find(name);
- if (i != symbols.end())
- return (*i).second;
- else if (parent)
- return parent->lookup(name);
- return NULL;
- }
-};
-
-extern std::auto_ptr<scope_t> global_scope;
-
-extern datetime_t terminus;
-extern bool initialized;
-
-void init_value_expr();
-
-bool compute_amount(value_expr_t * expr, amount_t& amt,
- const transaction_t * xact,
- value_expr_t * context = NULL);
-
-#define PARSE_VALEXPR_NORMAL 0x00
-#define PARSE_VALEXPR_PARTIAL 0x01
-#define PARSE_VALEXPR_RELAXED 0x02
-#define PARSE_VALEXPR_NO_MIGRATE 0x04
-#define PARSE_VALEXPR_NO_REDUCE 0x08
-
-value_expr_t * parse_value_expr(std::istream& in,
- scope_t * scope = NULL,
- const short flags = PARSE_VALEXPR_RELAXED);
-
-inline value_expr_t *
-parse_value_expr(const std::string& str,
- scope_t * scope = NULL,
- const short flags = PARSE_VALEXPR_RELAXED) {
- std::istringstream stream(str);
- try {
- return parse_value_expr(stream, scope, flags);
- }
- catch (error * err) {
- err->context.push_back
- (new line_context(str, (long)stream.tellg() - 1,
- "While parsing value expression:"));
- throw err;
- }
-}
-
-inline value_expr_t *
-parse_value_expr(const char * p,
- scope_t * scope = NULL,
- const short flags = PARSE_VALEXPR_RELAXED) {
- return parse_value_expr(std::string(p), scope, flags);
-}
-
-void dump_value_expr(std::ostream& out, const value_expr_t * node,
- const int depth = 0);
-
-bool write_value_expr(std::ostream& out,
- const value_expr_t * node,
- const bool relaxed = true,
- const value_expr_t * node_to_find = NULL,
- unsigned long * start_pos = NULL,
- unsigned long * end_pos = NULL);
-
-//////////////////////////////////////////////////////////////////////
-
-inline void guarded_compute(const value_expr_t * expr,
- value_t& result,
- const details_t& details = details_t(),
- value_expr_t * context = NULL) {
- try {
- expr->compute(result, details);
- }
- catch (error * err) {
- if (err->context.empty() ||
- ! dynamic_cast<valexpr_context *>(err->context.back()))
- err->context.push_back(new valexpr_context(expr));
- error_context * last = err->context.back();
- if (valexpr_context * ctxt = dynamic_cast<valexpr_context *>(last)) {
- ctxt->expr = expr->acquire();
- ctxt->desc = "While computing value expression:";
- }
- throw err;
- }
-}
-
-inline value_t guarded_compute(const value_expr_t * expr,
- const details_t& details = details_t(),
- value_expr_t * context = NULL) {
- value_t temp;
- guarded_compute(expr, temp, details, context);
- return temp;
-}
-
-//////////////////////////////////////////////////////////////////////
-
-class value_expr
-{
- value_expr_t * ptr;
-public:
- std::string expr;
-
- value_expr() : ptr(NULL) {}
-
- value_expr(const std::string& _expr) : expr(_expr) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr");
- if (! _expr.empty())
- ptr = parse_value_expr(expr)->acquire();
- else
- ptr = NULL;
- }
- value_expr(value_expr_t * _ptr)
- : ptr(_ptr ? _ptr->acquire(): NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr");
- }
- value_expr(const value_expr& other)
- : ptr(other.ptr ? other.ptr->acquire() : NULL),
- expr(other.expr) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr");
- }
- virtual ~value_expr() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor value_expr");
- if (ptr)
- ptr->release();
- }
-
- value_expr& operator=(const std::string& _expr) {
- expr = _expr;
- reset(parse_value_expr(expr));
- return *this;
- }
- value_expr& operator=(value_expr_t * _expr) {
- expr = "";
- reset(_expr);
- return *this;
- }
- value_expr& operator=(const value_expr& _expr) {
- expr = _expr.expr;
- reset(_expr.get());
- return *this;
- }
-
- operator bool() const throw() {
- return ptr != NULL;
- }
- operator std::string() const throw() {
- return expr;
- }
- operator value_expr_t *() const throw() {
- return ptr;
- }
-
- value_expr_t& operator*() const throw() {
- return *ptr;
- }
- value_expr_t * operator->() const throw() {
- return ptr;
- }
-
- value_expr_t * get() const throw() { return ptr; }
- value_expr_t * release() throw() {
- value_expr_t * tmp = ptr;
- ptr = 0;
- return tmp;
- }
- void reset(value_expr_t * p = 0) throw() {
- if (p != ptr) {
- if (ptr)
- ptr->release();
- ptr = p ? p->acquire() : NULL;
- }
- }
-
- virtual void compute(value_t& result,
- const details_t& details = details_t(),
- value_expr_t * context = NULL) {
- guarded_compute(ptr, result, details, context);
- }
- virtual value_t compute(const details_t& details = details_t(),
- value_expr_t * context = NULL) {
- value_t temp;
- guarded_compute(ptr, temp, details, context);
- return temp;
- }
-
- friend bool write_value_expr(std::ostream& out,
- const value_expr_t * node,
- const value_expr_t * node_to_find,
- unsigned long * start_pos,
- unsigned long * end_pos);
-};
-
-extern value_expr amount_expr;
-extern value_expr total_expr;
-
-inline void compute_amount(value_t& result,
- const details_t& details = details_t()) {
- if (amount_expr)
- amount_expr->compute(result, details);
-}
-
-inline value_t compute_amount(const details_t& details = details_t()) {
- if (amount_expr)
- return amount_expr->compute(details);
-}
-
-inline void compute_total(value_t& result,
- const details_t& details = details_t()) {
- if (total_expr)
- total_expr->compute(result, details);
-}
-
-inline value_t compute_total(const details_t& details = details_t()) {
- if (total_expr)
- return total_expr->compute(details);
-}
-
-value_expr_t * parse_boolean_expr(std::istream& in, scope_t * scope,
- const short flags);
-
-inline void parse_value_definition(const std::string& str,
- scope_t * scope = NULL) {
- std::istringstream def(str);
- value_expr expr
- (parse_boolean_expr(def, scope ? scope : global_scope.get(),
- PARSE_VALEXPR_RELAXED));
-}
-
-//////////////////////////////////////////////////////////////////////
-
-template <typename T>
-class item_predicate
-{
- public:
- const value_expr_t * predicate;
-
- item_predicate(const std::string& _predicate) : predicate(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor item_predicate<T>");
- if (! _predicate.empty())
- predicate = parse_value_expr(_predicate)->acquire();
- }
- item_predicate(const value_expr_t * _predicate = NULL)
- : predicate(_predicate->acquire()) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor item_predicate<T>");
- }
-
- ~item_predicate() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor item_predicate<T>");
- if (predicate)
- predicate->release();
- }
-
- bool operator()(const T& item) const {
- return (! predicate ||
- predicate->compute(details_t(item)).strip_annotations());
- }
-};
-
-} // namespace ledger
-
-#endif // _VALEXPR_H
diff --git a/value.cc b/value.cc
deleted file mode 100644
index 4bb74650..00000000
--- a/value.cc
+++ /dev/null
@@ -1,1696 +0,0 @@
-#include "value.h"
-#include "debug.h"
-#include "error.h"
-
-namespace ledger {
-
-void value_t::destroy()
-{
- switch (type) {
- case AMOUNT:
- ((amount_t *)data)->~amount_t();
- break;
- case BALANCE:
- ((balance_t *)data)->~balance_t();
- break;
- case BALANCE_PAIR:
- ((balance_pair_t *)data)->~balance_pair_t();
- break;
- default:
- break;
- }
-}
-
-void value_t::simplify()
-{
- if (realzero()) {
- DEBUG_PRINT("amounts.values.simplify", "Zeroing type " << type);
- *this = 0L;
- return;
- }
-
- if (type == BALANCE_PAIR &&
- (! ((balance_pair_t *) data)->cost ||
- ((balance_pair_t *) data)->cost->realzero())) {
- DEBUG_PRINT("amounts.values.simplify", "Reducing balance pair to balance");
- cast(BALANCE);
- }
-
- if (type == BALANCE &&
- ((balance_t *) data)->amounts.size() == 1) {
- DEBUG_PRINT("amounts.values.simplify", "Reducing balance to amount");
- cast(AMOUNT);
- }
-
- if (type == AMOUNT &&
- ! ((amount_t *) data)->commodity()) {
- DEBUG_PRINT("amounts.values.simplify", "Reducing amount to integer");
- cast(INTEGER);
- }
-}
-
-value_t& value_t::operator=(const value_t& value)
-{
- if (this == &value)
- return *this;
-
- destroy();
-
- switch (value.type) {
- case BOOLEAN:
- *((bool *) data) = *((bool *) value.data);
- break;
-
- case INTEGER:
- *((long *) data) = *((long *) value.data);
- break;
-
- case DATETIME:
- *((datetime_t *) data) = *((datetime_t *) value.data);
- break;
-
- case AMOUNT:
- new((amount_t *)data) amount_t(*((amount_t *) value.data));
- break;
-
- case BALANCE:
- new((balance_t *)data) balance_t(*((balance_t *) value.data));
- break;
-
- case BALANCE_PAIR:
- new((balance_pair_t *)data) balance_pair_t(*((balance_pair_t *) value.data));
- break;
-
- default:
- assert(0);
- break;
- }
-
- type = value.type;
-
- return *this;
-}
-
-value_t& value_t::operator+=(const value_t& value)
-{
- if (value.type == BOOLEAN)
- throw new value_error("Cannot add a boolean to a value");
- else if (value.type == DATETIME)
- throw new value_error("Cannot add a date/time to a value");
-
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot add a value to a boolean");
-
- case INTEGER:
- switch (value.type) {
- case INTEGER:
- *((long *) data) += *((long *) value.data);
- break;
- case AMOUNT:
- cast(AMOUNT);
- *((amount_t *) data) += *((amount_t *) value.data);
- break;
- case BALANCE:
- cast(BALANCE);
- *((balance_t *) data) += *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) += *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case DATETIME:
- switch (value.type) {
- case INTEGER:
- *((datetime_t *) data) += *((long *) value.data);
- break;
- case AMOUNT:
- *((datetime_t *) data) += long(*((amount_t *) value.data));
- break;
- case BALANCE:
- *((datetime_t *) data) += long(*((balance_t *) value.data));
- break;
- case BALANCE_PAIR:
- *((datetime_t *) data) += long(*((balance_pair_t *) value.data));
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case AMOUNT:
- switch (value.type) {
- case INTEGER:
- if (*((long *) value.data) &&
- ((amount_t *) data)->commodity()) {
- cast(BALANCE);
- return *this += value;
- }
- *((amount_t *) data) += *((long *) value.data);
- break;
-
- case AMOUNT:
- if (((amount_t *) data)->commodity() !=
- ((amount_t *) value.data)->commodity()) {
- cast(BALANCE);
- return *this += value;
- }
- *((amount_t *) data) += *((amount_t *) value.data);
- break;
-
- case BALANCE:
- cast(BALANCE);
- *((balance_t *) data) += *((balance_t *) value.data);
- break;
-
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) += *((balance_pair_t *) value.data);
- break;
-
- default:
- assert(0);
- break;
- }
- break;
-
- case BALANCE:
- switch (value.type) {
- case INTEGER:
- *((balance_t *) data) += *((long *) value.data);
- break;
- case AMOUNT:
- *((balance_t *) data) += *((amount_t *) value.data);
- break;
- case BALANCE:
- *((balance_t *) data) += *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) += *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case BALANCE_PAIR:
- switch (value.type) {
- case INTEGER:
- *((balance_pair_t *) data) += *((long *) value.data);
- break;
- case AMOUNT:
- *((balance_pair_t *) data) += *((amount_t *) value.data);
- break;
- case BALANCE:
- *((balance_pair_t *) data) += *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- *((balance_pair_t *) data) += *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- default:
- assert(0);
- break;
- }
- return *this;
-}
-
-value_t& value_t::operator-=(const value_t& value)
-{
- if (value.type == BOOLEAN)
- throw new value_error("Cannot subtract a boolean from a value");
- else if (value.type == DATETIME && type != DATETIME)
- throw new value_error("Cannot subtract a date/time from a value");
-
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot subtract a value from a boolean");
-
- case INTEGER:
- switch (value.type) {
- case INTEGER:
- *((long *) data) -= *((long *) value.data);
- break;
- case AMOUNT:
- cast(AMOUNT);
- *((amount_t *) data) -= *((amount_t *) value.data);
- break;
- case BALANCE:
- cast(BALANCE);
- *((balance_t *) data) -= *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) -= *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case DATETIME:
- switch (value.type) {
- case INTEGER:
- *((datetime_t *) data) -= *((long *) value.data);
- break;
- case DATETIME: {
- long val = *((datetime_t *) data) - *((datetime_t *) value.data);
- cast(INTEGER);
- *((long *) data) = val;
- break;
- }
- case AMOUNT:
- *((datetime_t *) data) -= long(*((amount_t *) value.data));
- break;
- case BALANCE:
- *((datetime_t *) data) -= long(*((balance_t *) value.data));
- break;
- case BALANCE_PAIR:
- *((datetime_t *) data) -= long(*((balance_pair_t *) value.data));
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case AMOUNT:
- switch (value.type) {
- case INTEGER:
- if (*((long *) value.data) &&
- ((amount_t *) data)->commodity()) {
- cast(BALANCE);
- return *this -= value;
- }
- *((amount_t *) data) -= *((long *) value.data);
- break;
-
- case AMOUNT:
- if (((amount_t *) data)->commodity() !=
- ((amount_t *) value.data)->commodity()) {
- cast(BALANCE);
- return *this -= value;
- }
- *((amount_t *) data) -= *((amount_t *) value.data);
- break;
-
- case BALANCE:
- cast(BALANCE);
- *((balance_t *) data) -= *((balance_t *) value.data);
- break;
-
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) -= *((balance_pair_t *) value.data);
- break;
-
- default:
- assert(0);
- break;
- }
- break;
-
- case BALANCE:
- switch (value.type) {
- case INTEGER:
- *((balance_t *) data) -= *((long *) value.data);
- break;
- case AMOUNT:
- *((balance_t *) data) -= *((amount_t *) value.data);
- break;
- case BALANCE:
- *((balance_t *) data) -= *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) -= *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case BALANCE_PAIR:
- switch (value.type) {
- case INTEGER:
- *((balance_pair_t *) data) -= *((long *) value.data);
- break;
- case AMOUNT:
- *((balance_pair_t *) data) -= *((amount_t *) value.data);
- break;
- case BALANCE:
- *((balance_pair_t *) data) -= *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- *((balance_pair_t *) data) -= *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- default:
- assert(0);
- break;
- }
-
- simplify();
-
- return *this;
-}
-
-value_t& value_t::operator*=(const value_t& value)
-{
- if (value.type == BOOLEAN)
- throw new value_error("Cannot multiply a boolean by a value");
- else if (value.type == DATETIME)
- throw new value_error("Cannot multiply a date/time by a value");
-
- if (value.realzero()) {
- *this = 0L;
- return *this;
- }
-
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot multiply a value by a boolean");
-
- case INTEGER:
- switch (value.type) {
- case INTEGER:
- *((long *) data) *= *((long *) value.data);
- break;
- case AMOUNT:
- cast(AMOUNT);
- *((amount_t *) data) *= *((amount_t *) value.data);
- break;
- case BALANCE:
- cast(BALANCE);
- *((balance_t *) data) *= *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) *= *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case AMOUNT:
- switch (value.type) {
- case INTEGER:
- *((amount_t *) data) *= *((long *) value.data);
- break;
- case AMOUNT:
- *((amount_t *) data) *= *((amount_t *) value.data);
- break;
- case BALANCE:
- cast(BALANCE);
- *((balance_t *) data) *= *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) *= *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case BALANCE:
- switch (value.type) {
- case INTEGER:
- *((balance_t *) data) *= *((long *) value.data);
- break;
- case AMOUNT:
- *((balance_t *) data) *= *((amount_t *) value.data);
- break;
- case BALANCE:
- *((balance_t *) data) *= *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) *= *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case BALANCE_PAIR:
- switch (value.type) {
- case INTEGER:
- *((balance_pair_t *) data) *= *((long *) value.data);
- break;
- case AMOUNT:
- *((balance_pair_t *) data) *= *((amount_t *) value.data);
- break;
- case BALANCE:
- *((balance_pair_t *) data) *= *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- *((balance_pair_t *) data) *= *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- default:
- assert(0);
- break;
- }
- return *this;
-}
-
-value_t& value_t::operator/=(const value_t& value)
-{
- if (value.type == BOOLEAN)
- throw new value_error("Cannot divide a boolean by a value");
- else if (value.type == DATETIME)
- throw new value_error("Cannot divide a date/time by a value");
-
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot divide a value by a boolean");
-
- case INTEGER:
- switch (value.type) {
- case INTEGER:
- *((long *) data) /= *((long *) value.data);
- break;
- case AMOUNT:
- cast(AMOUNT);
- *((amount_t *) data) /= *((amount_t *) value.data);
- break;
- case BALANCE:
- cast(BALANCE);
- *((balance_t *) data) /= *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) /= *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case AMOUNT:
- switch (value.type) {
- case INTEGER:
- *((amount_t *) data) /= *((long *) value.data);
- break;
- case AMOUNT:
- *((amount_t *) data) /= *((amount_t *) value.data);
- break;
- case BALANCE:
- cast(BALANCE);
- *((balance_t *) data) /= *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) /= *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case BALANCE:
- switch (value.type) {
- case INTEGER:
- *((balance_t *) data) /= *((long *) value.data);
- break;
- case AMOUNT:
- *((balance_t *) data) /= *((amount_t *) value.data);
- break;
- case BALANCE:
- *((balance_t *) data) /= *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- cast(BALANCE_PAIR);
- *((balance_pair_t *) data) /= *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- case BALANCE_PAIR:
- switch (value.type) {
- case INTEGER:
- *((balance_pair_t *) data) /= *((long *) value.data);
- break;
- case AMOUNT:
- *((balance_pair_t *) data) /= *((amount_t *) value.data);
- break;
- case BALANCE:
- *((balance_pair_t *) data) /= *((balance_t *) value.data);
- break;
- case BALANCE_PAIR:
- *((balance_pair_t *) data) /= *((balance_pair_t *) value.data);
- break;
- default:
- assert(0);
- break;
- }
- break;
-
- default:
- assert(0);
- break;
- }
- return *this;
-}
-
-#define DEF_VALUE_CMP_OP(OP) \
-bool value_t::operator OP(const value_t& value) \
-{ \
- switch (type) { \
- case BOOLEAN: \
- switch (value.type) { \
- case BOOLEAN: \
- return *((bool *) data) OP *((bool *) value.data); \
- \
- case INTEGER: \
- return *((bool *) data) OP bool(*((long *) value.data)); \
- \
- case DATETIME: \
- return *((bool *) data) OP bool(*((datetime_t *) value.data)); \
- \
- case AMOUNT: \
- return *((bool *) data) OP bool(*((amount_t *) value.data)); \
- \
- case BALANCE: \
- return *((bool *) data) OP bool(*((balance_t *) value.data)); \
- \
- case BALANCE_PAIR: \
- return *((bool *) data) OP bool(*((balance_pair_t *) value.data)); \
- \
- default: \
- assert(0); \
- break; \
- } \
- break; \
- \
- case INTEGER: \
- switch (value.type) { \
- case BOOLEAN: \
- return (*((long *) data) OP \
- ((long) *((bool *) value.data))); \
- \
- case INTEGER: \
- return (*((long *) data) OP *((long *) value.data)); \
- \
- case DATETIME: \
- return (*((long *) data) OP \
- ((long) ((datetime_t *) value.data)->when)); \
- \
- case AMOUNT: \
- return (amount_t(*((long *) data)) OP \
- *((amount_t *) value.data)); \
- \
- case BALANCE: \
- return (balance_t(*((long *) data)) OP \
- *((balance_t *) value.data)); \
- \
- case BALANCE_PAIR: \
- return (balance_pair_t(*((long *) data)) OP \
- *((balance_pair_t *) value.data)); \
- \
- default: \
- assert(0); \
- break; \
- } \
- break; \
- \
- case DATETIME: \
- switch (value.type) { \
- case BOOLEAN: \
- throw new value_error("Cannot compare a date/time to a boolean"); \
- \
- case INTEGER: \
- return (*((datetime_t *) data) OP \
- datetime_t(std::time_t(*((long *) value.data)))); \
- \
- case DATETIME: \
- return (*((datetime_t *) data) OP \
- *((datetime_t *) value.data)); \
- \
- case AMOUNT: \
- throw new value_error("Cannot compare a date/time to an amount"); \
- \
- case BALANCE: \
- throw new value_error("Cannot compare a date/time to a balance"); \
- \
- case BALANCE_PAIR: \
- throw new value_error("Cannot compare a date/time to a balance pair"); \
- \
- default: \
- assert(0); \
- break; \
- } \
- break; \
- \
- case AMOUNT: \
- switch (value.type) { \
- case BOOLEAN: \
- throw new value_error("Cannot compare an amount to a boolean"); \
- \
- case INTEGER: \
- return (*((amount_t *) data) OP \
- amount_t(*((long *) value.data))); \
- \
- case DATETIME: \
- throw new value_error("Cannot compare an amount to a date/time"); \
- \
- case AMOUNT: \
- return *((amount_t *) data) OP *((amount_t *) value.data); \
- \
- case BALANCE: \
- return (balance_t(*((amount_t *) data)) OP \
- *((balance_t *) value.data)); \
- \
- case BALANCE_PAIR: \
- return (balance_t(*((amount_t *) data)) OP \
- *((balance_pair_t *) value.data)); \
- \
- default: \
- assert(0); \
- break; \
- } \
- break; \
- \
- case BALANCE: \
- switch (value.type) { \
- case BOOLEAN: \
- throw new value_error("Cannot compare a balance to a boolean"); \
- \
- case INTEGER: \
- return *((balance_t *) data) OP *((long *) value.data); \
- \
- case DATETIME: \
- throw new value_error("Cannot compare a balance to a date/time"); \
- \
- case AMOUNT: \
- return *((balance_t *) data) OP *((amount_t *) value.data); \
- \
- case BALANCE: \
- return *((balance_t *) data) OP *((balance_t *) value.data); \
- \
- case BALANCE_PAIR: \
- return (*((balance_t *) data) OP \
- ((balance_pair_t *) value.data)->quantity); \
- \
- default: \
- assert(0); \
- break; \
- } \
- break; \
- \
- case BALANCE_PAIR: \
- switch (value.type) { \
- case BOOLEAN: \
- throw new value_error("Cannot compare a balance pair to a boolean"); \
- \
- case INTEGER: \
- return (((balance_pair_t *) data)->quantity OP \
- *((long *) value.data)); \
- \
- case DATETIME: \
- throw new value_error("Cannot compare a balance pair to a date/time"); \
- \
- case AMOUNT: \
- return (((balance_pair_t *) data)->quantity OP \
- *((amount_t *) value.data)); \
- \
- case BALANCE: \
- return (((balance_pair_t *) data)->quantity OP \
- *((balance_t *) value.data)); \
- \
- case BALANCE_PAIR: \
- return (*((balance_pair_t *) data) OP \
- *((balance_pair_t *) value.data)); \
- \
- default: \
- assert(0); \
- break; \
- } \
- break; \
- \
- default: \
- assert(0); \
- break; \
- } \
- return *this; \
-}
-
-DEF_VALUE_CMP_OP(==)
-DEF_VALUE_CMP_OP(<)
-DEF_VALUE_CMP_OP(<=)
-DEF_VALUE_CMP_OP(>)
-DEF_VALUE_CMP_OP(>=)
-
-template <>
-value_t::operator long() const
-{
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot convert a boolean to an integer");
- case INTEGER:
- return *((long *) data);
- case DATETIME:
- return ((datetime_t *) data)->when;
- case AMOUNT:
- return *((amount_t *) data);
- case BALANCE:
- throw new value_error("Cannot convert a balance to an integer");
- case BALANCE_PAIR:
- throw new value_error("Cannot convert a balance pair to an integer");
-
- default:
- assert(0);
- break;
- }
- assert(0);
- return 0;
-}
-
-template <>
-value_t::operator datetime_t() const
-{
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot convert a boolean to a date/time");
- case INTEGER:
- return *((long *) data);
- case DATETIME:
- return *((datetime_t *) data);
- case AMOUNT:
- throw new value_error("Cannot convert an amount to a date/time");
- case BALANCE:
- throw new value_error("Cannot convert a balance to a date/time");
- case BALANCE_PAIR:
- throw new value_error("Cannot convert a balance pair to a date/time");
-
- default:
- assert(0);
- break;
- }
- assert(0);
- return 0;
-}
-
-template <>
-value_t::operator double() const
-{
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot convert a boolean to a double");
- case INTEGER:
- return *((long *) data);
- case DATETIME:
- throw new value_error("Cannot convert a date/time to a double");
- case AMOUNT:
- return *((amount_t *) data);
- case BALANCE:
- throw new value_error("Cannot convert a balance to a double");
- case BALANCE_PAIR:
- throw new value_error("Cannot convert a balance pair to a double");
-
- default:
- assert(0);
- break;
- }
- assert(0);
- return 0;
-}
-
-void value_t::cast(type_t cast_type)
-{
- switch (type) {
- case BOOLEAN:
- switch (cast_type) {
- case BOOLEAN:
- break;
- case INTEGER:
- throw new value_error("Cannot convert a boolean to an integer");
- case DATETIME:
- throw new value_error("Cannot convert a boolean to a date/time");
- case AMOUNT:
- throw new value_error("Cannot convert a boolean to an amount");
- case BALANCE:
- throw new value_error("Cannot convert a boolean to a balance");
- case BALANCE_PAIR:
- throw new value_error("Cannot convert a boolean to a balance pair");
-
- default:
- assert(0);
- break;
- }
- break;
-
- case INTEGER:
- switch (cast_type) {
- case BOOLEAN:
- *((bool *) data) = *((long *) data);
- break;
- case INTEGER:
- break;
- case DATETIME:
- *((datetime_t *) data) = datetime_t(std::time_t(*((long *) data)));
- break;
- case AMOUNT:
- new((amount_t *)data) amount_t(*((long *) data));
- break;
- case BALANCE:
- new((balance_t *)data) balance_t(amount_t(*((long *) data)));
- break;
- case BALANCE_PAIR:
- new((balance_pair_t *)data) balance_pair_t(amount_t(*((long *) data)));
- break;
-
- default:
- assert(0);
- break;
- }
- break;
-
- case DATETIME:
- switch (cast_type) {
- case BOOLEAN:
- *((bool *) data) = *((datetime_t *) data);
- break;
- case INTEGER:
- *((long *) data) = ((datetime_t *) data)->when;
- break;
- case DATETIME:
- break;
- case AMOUNT:
- throw new value_error("Cannot convert a date/time to an amount");
- case BALANCE:
- throw new value_error("Cannot convert a date/time to a balance");
- case BALANCE_PAIR:
- throw new value_error("Cannot convert a date/time to a balance pair");
-
- default:
- assert(0);
- break;
- }
- break;
-
- case AMOUNT:
- switch (cast_type) {
- case BOOLEAN: {
- bool temp = *((amount_t *) data);
- destroy();
- *((bool *)data) = temp;
- break;
- }
- case INTEGER: {
- long temp = *((amount_t *) data);
- destroy();
- *((long *)data) = temp;
- break;
- }
- case DATETIME:
- throw new value_error("Cannot convert an amount to a date/time");
- case AMOUNT:
- break;
- case BALANCE: {
- amount_t temp = *((amount_t *) data);
- destroy();
- new((balance_t *)data) balance_t(temp);
- break;
- }
- case BALANCE_PAIR: {
- amount_t temp = *((amount_t *) data);
- destroy();
- new((balance_pair_t *)data) balance_pair_t(temp);
- break;
- }
-
- default:
- assert(0);
- break;
- }
- break;
-
- case BALANCE:
- switch (cast_type) {
- case BOOLEAN: {
- bool temp = *((balance_t *) data);
- destroy();
- *((bool *)data) = temp;
- break;
- }
- case INTEGER:
- throw new value_error("Cannot convert a balance to an integer");
- case DATETIME:
- throw new value_error("Cannot convert a balance to a date/time");
-
- case AMOUNT: {
- balance_t * temp = (balance_t *) data;
- if (temp->amounts.size() == 1) {
- amount_t amt = (*temp->amounts.begin()).second;
- destroy();
- new((amount_t *)data) amount_t(amt);
- }
- else if (temp->amounts.size() == 0) {
- new((amount_t *)data) amount_t();
- }
- else {
- throw new value_error("Cannot convert a balance with "
- "multiple commodities to an amount");
- }
- break;
- }
- case BALANCE:
- break;
- case BALANCE_PAIR: {
- balance_t temp = *((balance_t *) data);
- destroy();
- new((balance_pair_t *)data) balance_pair_t(temp);
- break;
- }
-
- default:
- assert(0);
- break;
- }
- break;
-
- case BALANCE_PAIR:
- switch (cast_type) {
- case BOOLEAN: {
- bool temp = *((balance_pair_t *) data);
- destroy();
- *((bool *)data) = temp;
- break;
- }
- case INTEGER:
- throw new value_error("Cannot convert a balance pair to an integer");
- case DATETIME:
- throw new value_error("Cannot convert a balance pair to a date/time");
-
- case AMOUNT: {
- balance_t * temp = &((balance_pair_t *) data)->quantity;
- if (temp->amounts.size() == 1) {
- amount_t amt = (*temp->amounts.begin()).second;
- destroy();
- new((amount_t *)data) amount_t(amt);
- }
- else if (temp->amounts.size() == 0) {
- new((amount_t *)data) amount_t();
- }
- else {
- throw new value_error("Cannot convert a balance pair with "
- "multiple commodities to an amount");
- }
- break;
- }
- case BALANCE: {
- balance_t temp = ((balance_pair_t *) data)->quantity;
- destroy();
- new((balance_t *)data) balance_t(temp);
- break;
- }
- case BALANCE_PAIR:
- break;
-
- default:
- assert(0);
- break;
- }
- break;
-
- default:
- assert(0);
- break;
- }
- type = cast_type;
-}
-
-void value_t::negate()
-{
- switch (type) {
- case BOOLEAN:
- *((bool *) data) = ! *((bool *) data);
- break;
- case INTEGER:
- *((long *) data) = - *((long *) data);
- break;
- case DATETIME:
- cast(INTEGER);
- negate();
- break;
- case AMOUNT:
- ((amount_t *) data)->negate();
- break;
- case BALANCE:
- ((balance_t *) data)->negate();
- break;
- case BALANCE_PAIR:
- ((balance_pair_t *) data)->negate();
- break;
-
- default:
- assert(0);
- break;
- }
-}
-
-void value_t::abs()
-{
- switch (type) {
- case BOOLEAN:
- break;
- case INTEGER:
- if (*((long *) data) < 0)
- *((long *) data) = - *((long *) data);
- break;
- case DATETIME:
- break;
- case AMOUNT:
- ((amount_t *) data)->abs();
- break;
- case BALANCE:
- ((balance_t *) data)->abs();
- break;
- case BALANCE_PAIR:
- ((balance_pair_t *) data)->abs();
- break;
-
- default:
- assert(0);
- break;
- }
-}
-
-value_t value_t::value(const datetime_t& moment) const
-{
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot find the value of a boolean");
- case DATETIME:
- throw new value_error("Cannot find the value of a date/time");
- case INTEGER:
- return *this;
- case AMOUNT:
- return ((amount_t *) data)->value(moment);
- case BALANCE:
- return ((balance_t *) data)->value(moment);
- case BALANCE_PAIR:
- return ((balance_pair_t *) data)->quantity.value(moment);
- }
-}
-
-void value_t::reduce()
-{
- switch (type) {
- case BOOLEAN:
- case DATETIME:
- case INTEGER:
- break;
- case AMOUNT:
- ((amount_t *) data)->reduce();
- break;
- case BALANCE:
- ((balance_t *) data)->reduce();
- break;
- case BALANCE_PAIR:
- ((balance_pair_t *) data)->reduce();
- break;
- }
-}
-
-void value_t::round()
-{
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot round a boolean");
- case DATETIME:
- throw new value_error("Cannot round a date/time");
- case INTEGER:
- break;
- case AMOUNT:
- *((amount_t *) data) = ((amount_t *) data)->round();
- break;
- case BALANCE:
- ((balance_t *) data)->round();
- break;
- case BALANCE_PAIR:
- ((balance_pair_t *) data)->round();
- break;
- }
-}
-
-value_t value_t::unround() const
-{
- value_t temp;
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot un-round a boolean");
- case DATETIME:
- throw new value_error("Cannot un-round a date/time");
- case INTEGER:
- break;
- case AMOUNT:
- temp = ((amount_t *) data)->unround();
- break;
- case BALANCE:
- temp = ((balance_t *) data)->unround();
- break;
- case BALANCE_PAIR:
- temp = ((balance_pair_t *) data)->unround();
- break;
- }
- return temp;
-}
-
-value_t value_t::price() const
-{
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot find the price of a boolean");
- case INTEGER:
- return *this;
- case DATETIME:
- throw new value_error("Cannot find the price of a date/time");
-
- case AMOUNT:
- return ((amount_t *) data)->price();
-
- case BALANCE:
- return ((balance_t *) data)->price();
-
- case BALANCE_PAIR:
- return ((balance_pair_t *) data)->quantity.price();
-
- default:
- assert(0);
- break;
- }
- assert(0);
- return value_t();
-}
-
-value_t value_t::date() const
-{
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot find the date of a boolean");
- case INTEGER:
- return datetime_t();
- case DATETIME:
- return *this;
-
- case AMOUNT:
- return datetime_t(((amount_t *) data)->date());
-
- case BALANCE:
- return datetime_t(((balance_t *) data)->date());
-
- case BALANCE_PAIR:
- return datetime_t(((balance_pair_t *) data)->quantity.date());
-
- default:
- assert(0);
- break;
- }
- assert(0);
- return value_t();
-}
-
-value_t value_t::strip_annotations(const bool keep_price,
- const bool keep_date,
- const bool keep_tag) const
-{
- switch (type) {
- case BOOLEAN:
- case INTEGER:
- case DATETIME:
- return *this;
-
- case AMOUNT:
- return ((amount_t *) data)->strip_annotations
- (keep_price, keep_date, keep_tag);
- case BALANCE:
- return ((balance_t *) data)->strip_annotations
- (keep_price, keep_date, keep_tag);
- case BALANCE_PAIR:
- return ((balance_pair_t *) data)->quantity.strip_annotations
- (keep_price, keep_date, keep_tag);
-
- default:
- assert(0);
- break;
- }
- assert(0);
- return value_t();
-}
-
-value_t value_t::cost() const
-{
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot find the cost of a boolean");
- case INTEGER:
- case AMOUNT:
- case BALANCE:
- return *this;
- case DATETIME:
- throw new value_error("Cannot find the cost of a date/time");
-
- case BALANCE_PAIR:
- assert(((balance_pair_t *) data)->cost);
- if (((balance_pair_t *) data)->cost)
- return *(((balance_pair_t *) data)->cost);
- else
- return ((balance_pair_t *) data)->quantity;
-
- default:
- assert(0);
- break;
- }
- assert(0);
- return value_t();
-}
-
-value_t& value_t::add(const amount_t& amount, const amount_t * cost)
-{
- switch (type) {
- case BOOLEAN:
- throw new value_error("Cannot add an amount to a boolean");
- case DATETIME:
- throw new value_error("Cannot add an amount to a date/time");
- case INTEGER:
- case AMOUNT:
- if (cost) {
- cast(BALANCE_PAIR);
- return add(amount, cost);
- }
- else if ((type == AMOUNT &&
- ((amount_t *) data)->commodity() != amount.commodity()) ||
- (type != AMOUNT && amount.commodity())) {
- cast(BALANCE);
- return add(amount, cost);
- }
- else if (type != AMOUNT) {
- cast(AMOUNT);
- }
- *((amount_t *) data) += amount;
- break;
-
- case BALANCE:
- if (cost) {
- cast(BALANCE_PAIR);
- return add(amount, cost);
- }
- *((balance_t *) data) += amount;
- break;
-
- case BALANCE_PAIR:
- ((balance_pair_t *) data)->add(amount, cost);
- break;
-
- default:
- assert(0);
- break;
- }
-
- return *this;
-}
-
-value_context::value_context(const value_t& _bal,
- const std::string& desc) throw()
- : bal(new value_t(_bal)), error_context(desc) {}
-
-value_context::~value_context() throw()
-{
- delete bal;
-}
-
-void value_context::describe(std::ostream& out) const throw()
-{
- if (! desc.empty())
- out << desc << std::endl;
-
- ledger::balance_t * ptr = NULL;
-
- out << std::right;
- out.width(20);
-
- switch (bal->type) {
- case ledger::value_t::BOOLEAN:
- out << (*((bool *) bal->data) ? "true" : "false");
- break;
- case ledger::value_t::INTEGER:
- out << *((long *) bal->data);
- break;
- case ledger::value_t::DATETIME:
- out << *((datetime_t *) bal->data);
- break;
- case ledger::value_t::AMOUNT:
- out << *((ledger::amount_t *) bal->data);
- break;
- case ledger::value_t::BALANCE:
- ptr = (ledger::balance_t *) bal->data;
- // fall through...
-
- case ledger::value_t::BALANCE_PAIR:
- if (! ptr)
- ptr = &((ledger::balance_pair_t *) bal->data)->quantity;
-
- ptr->write(out, 20);
- break;
- default:
- assert(0);
- break;
- }
- out << std::endl;
-}
-
-} // namespace ledger
-
-#ifdef USE_BOOST_PYTHON
-
-#include <boost/python.hpp>
-
-using namespace boost::python;
-using namespace ledger;
-
-long balance_len(balance_t& bal);
-amount_t balance_getitem(balance_t& bal, int i);
-long balance_pair_len(balance_pair_t& bal_pair);
-amount_t balance_pair_getitem(balance_pair_t& bal_pair, int i);
-
-long value_len(value_t& value)
-{
- switch (value.type) {
- case value_t::BOOLEAN:
- case value_t::INTEGER:
- case value_t::DATETIME:
- case value_t::AMOUNT:
- return 1;
-
- case value_t::BALANCE:
- return balance_len(*((balance_t *) value.data));
-
- case value_t::BALANCE_PAIR:
- return balance_pair_len(*((balance_pair_t *) value.data));
-
- default:
- assert(0);
- break;
- }
- assert(0);
- return 0;
-}
-
-amount_t value_getitem(value_t& value, int i)
-{
- std::size_t len = value_len(value);
-
- if (abs(i) >= len) {
- PyErr_SetString(PyExc_IndexError, "Index out of range");
- throw_error_already_set();
- }
-
- switch (value.type) {
- case value_t::BOOLEAN:
- throw new value_error("Cannot cast a boolean to an amount");
-
- case value_t::INTEGER:
- return long(value);
-
- case value_t::DATETIME:
- throw new value_error("Cannot cast a date/time to an amount");
-
- case value_t::AMOUNT:
- return *((amount_t *) value.data);
-
- case value_t::BALANCE:
- return balance_getitem(*((balance_t *) value.data), i);
-
- case value_t::BALANCE_PAIR:
- return balance_pair_getitem(*((balance_pair_t *) value.data), i);
-
- default:
- assert(0);
- break;
- }
- assert(0);
- return 0L;
-}
-
-double py_to_float(value_t& value)
-{
- return double(value);
-}
-
-void export_value()
-{
- scope in_value = class_< value_t > ("Value")
- .def(init<value_t>())
- .def(init<balance_pair_t>())
- .def(init<balance_t>())
- .def(init<amount_t>())
- .def(init<std::string>())
- .def(init<double>())
- .def(init<long>())
- .def(init<datetime_t>())
-
- .def(self + self)
- .def(self + other<balance_pair_t>())
- .def(self + other<balance_t>())
- .def(self + other<amount_t>())
- .def(self + long())
- .def(self + double())
-
- .def(other<balance_pair_t>() + self)
- .def(other<balance_t>() + self)
- .def(other<amount_t>() + self)
- .def(long() + self)
- .def(double() + self)
-
- .def(self - self)
- .def(self - other<balance_pair_t>())
- .def(self - other<balance_t>())
- .def(self - other<amount_t>())
- .def(self - long())
- .def(self - double())
-
- .def(other<balance_pair_t>() - self)
- .def(other<balance_t>() - self)
- .def(other<amount_t>() - self)
- .def(long() - self)
- .def(double() - self)
-
- .def(self * self)
- .def(self * other<balance_pair_t>())
- .def(self * other<balance_t>())
- .def(self * other<amount_t>())
- .def(self * long())
- .def(self * double())
-
- .def(other<balance_pair_t>() * self)
- .def(other<balance_t>() * self)
- .def(other<amount_t>() * self)
- .def(long() * self)
- .def(double() * self)
-
- .def(self / self)
- .def(self / other<balance_pair_t>())
- .def(self / other<balance_t>())
- .def(self / other<amount_t>())
- .def(self / long())
- .def(self / double())
-
- .def(other<balance_pair_t>() / self)
- .def(other<balance_t>() / self)
- .def(other<amount_t>() / self)
- .def(long() / self)
- .def(double() / self)
-
- .def(- self)
-
- .def(self += self)
- .def(self += other<balance_pair_t>())
- .def(self += other<balance_t>())
- .def(self += other<amount_t>())
- .def(self += long())
- .def(self += double())
-
- .def(self -= self)
- .def(self -= other<balance_pair_t>())
- .def(self -= other<balance_t>())
- .def(self -= other<amount_t>())
- .def(self -= long())
- .def(self -= double())
-
- .def(self *= self)
- .def(self *= other<balance_pair_t>())
- .def(self *= other<balance_t>())
- .def(self *= other<amount_t>())
- .def(self *= long())
- .def(self *= double())
-
- .def(self /= self)
- .def(self /= other<balance_pair_t>())
- .def(self /= other<balance_t>())
- .def(self /= other<amount_t>())
- .def(self /= long())
- .def(self /= double())
-
- .def(self < self)
- .def(self < other<balance_pair_t>())
- .def(self < other<balance_t>())
- .def(self < other<amount_t>())
- .def(self < long())
- .def(self < other<datetime_t>())
- .def(self < double())
-
- .def(other<balance_pair_t>() < self)
- .def(other<balance_t>() < self)
- .def(other<amount_t>() < self)
- .def(long() < self)
- .def(other<datetime_t>() < self)
- .def(double() < self)
-
- .def(self <= self)
- .def(self <= other<balance_pair_t>())
- .def(self <= other<balance_t>())
- .def(self <= other<amount_t>())
- .def(self <= long())
- .def(self <= other<datetime_t>())
- .def(self <= double())
-
- .def(other<balance_pair_t>() <= self)
- .def(other<balance_t>() <= self)
- .def(other<amount_t>() <= self)
- .def(long() <= self)
- .def(other<datetime_t>() <= self)
- .def(double() <= self)
-
- .def(self > self)
- .def(self > other<balance_pair_t>())
- .def(self > other<balance_t>())
- .def(self > other<amount_t>())
- .def(self > long())
- .def(self > other<datetime_t>())
- .def(self > double())
-
- .def(other<balance_pair_t>() > self)
- .def(other<balance_t>() > self)
- .def(other<amount_t>() > self)
- .def(long() > self)
- .def(other<datetime_t>() > self)
- .def(double() > self)
-
- .def(self >= self)
- .def(self >= other<balance_pair_t>())
- .def(self >= other<balance_t>())
- .def(self >= other<amount_t>())
- .def(self >= long())
- .def(self >= other<datetime_t>())
- .def(self >= double())
-
- .def(other<balance_pair_t>() >= self)
- .def(other<balance_t>() >= self)
- .def(other<amount_t>() >= self)
- .def(long() >= self)
- .def(other<datetime_t>() >= self)
- .def(double() >= self)
-
- .def(self == self)
- .def(self == other<balance_pair_t>())
- .def(self == other<balance_t>())
- .def(self == other<amount_t>())
- .def(self == long())
- .def(self == other<datetime_t>())
- .def(self == double())
-
- .def(other<balance_pair_t>() == self)
- .def(other<balance_t>() == self)
- .def(other<amount_t>() == self)
- .def(long() == self)
- .def(other<datetime_t>() == self)
- .def(double() == self)
-
- .def(self != self)
- .def(self != other<balance_pair_t>())
- .def(self != other<balance_t>())
- .def(self != other<amount_t>())
- .def(self != long())
- .def(self != other<datetime_t>())
- .def(self != double())
-
- .def(other<balance_pair_t>() != self)
- .def(other<balance_t>() != self)
- .def(other<amount_t>() != self)
- .def(long() != self)
- .def(other<datetime_t>() != self)
- .def(double() != self)
-
- .def(! self)
-
- .def(self_ns::int_(self))
- .def(self_ns::float_(self))
- .def(self_ns::str(self))
- .def(abs(self))
-
- .def_readonly("type", &value_t::type)
-
- .def("__len__", value_len)
- .def("__getitem__", value_getitem)
-
- .def("cast", &value_t::cast)
- .def("cost", &value_t::cost)
- .def("price", &value_t::price)
- .def("date", &value_t::date)
- .def("strip_annotations", &value_t::strip_annotations)
- .def("add", &value_t::add, return_internal_reference<>())
- .def("value", &value_t::value)
- .def("round", &value_t::round)
- .def("negate", &value_t::negate)
- .def("negated", &value_t::negated)
- ;
-
- enum_< value_t::type_t > ("ValueType")
- .value("BOOLEAN", value_t::BOOLEAN)
- .value("INTEGER", value_t::INTEGER)
- .value("DATETIME", value_t::DATETIME)
- .value("AMOUNT", value_t::AMOUNT)
- .value("BALANCE", value_t::BALANCE)
- .value("BALANCE_PAIR", value_t::BALANCE_PAIR)
- ;
-}
-
-#endif // USE_BOOST_PYTHON
diff --git a/value.h b/value.h
deleted file mode 100644
index fe01786b..00000000
--- a/value.h
+++ /dev/null
@@ -1,444 +0,0 @@
-#ifndef _VALUE_H
-#define _VALUE_H
-
-#include "amount.h"
-#include "balance.h"
-#include "error.h"
-
-#include <exception>
-
-namespace ledger {
-
-// The following type is a polymorphous value type used solely for
-// performance reasons. The alternative is to compute value
-// expressions (valexpr.cc) in terms of the largest data type,
-// balance_t. This was found to be prohibitively expensive, especially
-// when large logic chains were involved, since many temporary
-// allocations would occur for every operator. With value_t, and the
-// fact that logic chains only need boolean values to continue, no
-// memory allocations need to take place at all.
-
-class value_t
-{
- public:
- char data[sizeof(balance_pair_t)];
-
- enum type_t {
- BOOLEAN,
- INTEGER,
- DATETIME,
- AMOUNT,
- BALANCE,
- BALANCE_PAIR
- } type;
-
- value_t() {
- *((long *) data) = 0;
- type = INTEGER;
- }
-
- value_t(const value_t& value) : type(INTEGER) {
- *this = value;
- }
- value_t(const bool value) {
- *((bool *) data) = value;
- type = BOOLEAN;
- }
- value_t(const long value) {
- *((long *) data) = value;
- type = INTEGER;
- }
- value_t(const datetime_t value) {
- *((datetime_t *) data) = value;
- type = DATETIME;
- }
- value_t(const unsigned long value) {
- new((amount_t *) data) amount_t(value);
- type = AMOUNT;
- }
- value_t(const double value) {
- new((amount_t *) data) amount_t(value);
- type = AMOUNT;
- }
- value_t(const std::string& value) {
- new((amount_t *) data) amount_t(value);
- type = AMOUNT;
- }
- value_t(const char * value) {
- new((amount_t *) data) amount_t(value);
- type = AMOUNT;
- }
- value_t(const amount_t& value) {
- new((amount_t *)data) amount_t(value);
- type = AMOUNT;
- }
- value_t(const balance_t& value) : type(INTEGER) {
- *this = value;
- }
- value_t(const balance_pair_t& value) : type(INTEGER) {
- *this = value;
- }
-
- ~value_t() {
- destroy();
- }
-
- void destroy();
- void simplify();
-
- value_t& operator=(const value_t& value);
- value_t& operator=(const bool value) {
- if ((bool *) data != &value) {
- destroy();
- *((bool *) data) = value;
- type = BOOLEAN;
- }
- return *this;
- }
- value_t& operator=(const long value) {
- if ((long *) data != &value) {
- destroy();
- *((long *) data) = value;
- type = INTEGER;
- }
- return *this;
- }
- value_t& operator=(const datetime_t value) {
- if ((datetime_t *) data != &value) {
- destroy();
- *((datetime_t *) data) = value;
- type = DATETIME;
- }
- return *this;
- }
- value_t& operator=(const unsigned long value) {
- return *this = amount_t(value);
- }
- value_t& operator=(const double value) {
- return *this = amount_t(value);
- }
- value_t& operator=(const std::string& value) {
- return *this = amount_t(value);
- }
- value_t& operator=(const char * value) {
- return *this = amount_t(value);
- }
- value_t& operator=(const amount_t& value) {
- if (type == AMOUNT &&
- (amount_t *) data == &value)
- return *this;
-
- if (value.realzero()) {
- return *this = 0L;
- } else {
- destroy();
- new((amount_t *)data) amount_t(value);
- type = AMOUNT;
- }
- return *this;
- }
- value_t& operator=(const balance_t& value) {
- if (type == BALANCE &&
- (balance_t *) data == &value)
- return *this;
-
- if (value.realzero()) {
- return *this = 0L;
- }
- else if (value.amounts.size() == 1) {
- return *this = (*value.amounts.begin()).second;
- }
- else {
- destroy();
- new((balance_t *)data) balance_t(value);
- type = BALANCE;
- return *this;
- }
- }
- value_t& operator=(const balance_pair_t& value) {
- if (type == BALANCE_PAIR &&
- (balance_pair_t *) data == &value)
- return *this;
-
- if (value.realzero()) {
- return *this = 0L;
- }
- else if (! value.cost) {
- return *this = value.quantity;
- }
- else {
- destroy();
- new((balance_pair_t *)data) balance_pair_t(value);
- type = BALANCE_PAIR;
- return *this;
- }
- }
-
- value_t& operator+=(const value_t& value);
- value_t& operator-=(const value_t& value);
- value_t& operator*=(const value_t& value);
- value_t& operator/=(const value_t& value);
-
- template <typename T>
- value_t& operator+=(const T& value) {
- return *this += value_t(value);
- }
- template <typename T>
- value_t& operator-=(const T& value) {
- return *this -= value_t(value);
- }
- template <typename T>
- value_t& operator*=(const T& value) {
- return *this *= value_t(value);
- }
- template <typename T>
- value_t& operator/=(const T& value) {
- return *this /= value_t(value);
- }
-
- value_t operator+(const value_t& value) {
- value_t temp(*this);
- temp += value;
- return temp;
- }
- value_t operator-(const value_t& value) {
- value_t temp(*this);
- temp -= value;
- return temp;
- }
- value_t operator*(const value_t& value) {
- value_t temp(*this);
- temp *= value;
- return temp;
- }
- value_t operator/(const value_t& value) {
- value_t temp(*this);
- temp /= value;
- return temp;
- }
-
- template <typename T>
- value_t operator+(const T& value) {
- return *this + value_t(value);
- }
- template <typename T>
- value_t operator-(const T& value) {
- return *this - value_t(value);
- }
- template <typename T>
- value_t operator*(const T& value) {
- return *this * value_t(value);
- }
- template <typename T>
- value_t operator/(const T& value) {
- return *this / value_t(value);
- }
-
- bool operator<(const value_t& value);
- bool operator<=(const value_t& value);
- bool operator>(const value_t& value);
- bool operator>=(const value_t& value);
- bool operator==(const value_t& value);
- bool operator!=(const value_t& value) {
- return ! (*this == value);
- }
-
- template <typename T>
- bool operator<(const T& value) {
- return *this < value_t(value);
- }
- template <typename T>
- bool operator<=(const T& value) {
- return *this <= value_t(value);
- }
- template <typename T>
- bool operator>(const T& value) {
- return *this > value_t(value);
- }
- template <typename T>
- bool operator>=(const T& value) {
- return *this >= value_t(value);
- }
- template <typename T>
- bool operator==(const T& value) {
- return *this == value_t(value);
- }
- template <typename T>
- bool operator!=(const T& value) {
- return ! (*this == value);
- }
-
- template <typename T>
- operator T() const;
-
- void negate();
- value_t negated() const {
- value_t temp = *this;
- temp.negate();
- return temp;
- }
- value_t operator-() const {
- return negated();
- }
-
- bool realzero() const {
- switch (type) {
- case BOOLEAN:
- return ! *((bool *) data);
- case INTEGER:
- return *((long *) data) == 0;
- case DATETIME:
- return ! *((datetime_t *) data);
- case AMOUNT:
- return ((amount_t *) data)->realzero();
- case BALANCE:
- return ((balance_t *) data)->realzero();
- case BALANCE_PAIR:
- return ((balance_pair_t *) data)->realzero();
-
- default:
- assert(0);
- break;
- }
- assert(0);
- return 0;
- }
-
- void abs();
- void cast(type_t cast_type);
- value_t cost() const;
- value_t price() const;
- value_t date() const;
-
- value_t strip_annotations(const bool keep_price = amount_t::keep_price,
- const bool keep_date = amount_t::keep_date,
- const bool keep_tag = amount_t::keep_tag) const;
-
- value_t& add(const amount_t& amount, const amount_t * cost = NULL);
- value_t value(const datetime_t& moment) const;
- void reduce();
-
- value_t reduced() const {
- value_t temp(*this);
- temp.reduce();
- return temp;
- }
-
- void round();
- value_t unround() const;
-};
-
-#define DEF_VALUE_AUX_OP(OP) \
- inline value_t operator OP(const balance_pair_t& value, \
- const value_t& obj) { \
- return value_t(value) OP obj; \
- } \
- inline value_t operator OP(const balance_t& value, \
- const value_t& obj) { \
- return value_t(value) OP obj; \
- } \
- inline value_t operator OP(const amount_t& value, \
- const value_t& obj) { \
- return value_t(value) OP obj; \
- } \
- template <typename T> \
- inline value_t operator OP(T value, const value_t& obj) { \
- return value_t(value) OP obj; \
- }
-
-DEF_VALUE_AUX_OP(+)
-DEF_VALUE_AUX_OP(-)
-DEF_VALUE_AUX_OP(*)
-DEF_VALUE_AUX_OP(/)
-
-DEF_VALUE_AUX_OP(<)
-DEF_VALUE_AUX_OP(<=)
-DEF_VALUE_AUX_OP(>)
-DEF_VALUE_AUX_OP(>=)
-DEF_VALUE_AUX_OP(==)
-DEF_VALUE_AUX_OP(!=)
-
-template <typename T>
-value_t::operator T() const
-{
- switch (type) {
- case BOOLEAN:
- return *((bool *) data);
- case INTEGER:
- return *((long *) data);
- case DATETIME:
- return *((datetime_t *) data);
- case AMOUNT:
- return *((amount_t *) data);
- case BALANCE:
- return *((balance_t *) data);
- case BALANCE_PAIR:
- return *((balance_pair_t *) data);
-
- default:
- assert(0);
- break;
- }
- assert(0);
- return 0;
-}
-
-template <> value_t::operator long() const;
-template <> value_t::operator datetime_t() const;
-template <> value_t::operator double() const;
-
-inline value_t abs(const value_t& value) {
- value_t temp(value);
- temp.abs();
- return temp;
-}
-
-inline std::ostream& operator<<(std::ostream& out, const value_t& value) {
- switch (value.type) {
- case value_t::BOOLEAN:
- out << (*((bool *) value.data) ? "true" : "false");
- break;
- case value_t::INTEGER:
- out << *((long *) value.data);
- break;
- case value_t::DATETIME:
- out << *((datetime_t *) value.data);
- break;
- case value_t::AMOUNT:
- out << *((amount_t *) value.data);
- break;
- case value_t::BALANCE:
- out << *((balance_t *) value.data);
- break;
- case value_t::BALANCE_PAIR:
- out << *((balance_pair_t *) value.data);
- break;
-
- default:
- assert(0);
- break;
- }
- return out;
-}
-
-class value_context : public error_context
-{
- value_t * bal;
- public:
- value_context(const value_t& _bal,
- const std::string& desc = "") throw();
- virtual ~value_context() throw();
-
- virtual void describe(std::ostream& out) const throw();
-};
-
-class value_error : public error {
- public:
- value_error(const std::string& reason, error_context * ctxt = NULL) throw()
- : error(reason, ctxt) {}
- virtual ~value_error() throw() {}
-};
-
-} // namespace ledger
-
-#endif // _VALUE_H
diff --git a/walk.cc b/walk.cc
deleted file mode 100644
index 88b5461a..00000000
--- a/walk.cc
+++ /dev/null
@@ -1,911 +0,0 @@
-#include "walk.h"
-#include "format.h"
-#include "textual.h"
-#include "util.h"
-
-#include <algorithm>
-
-namespace ledger {
-
-template <>
-bool compare_items<transaction_t>::operator()(const transaction_t * left,
- const transaction_t * right)
-{
- assert(left);
- assert(right);
-
- transaction_xdata_t& lxdata(transaction_xdata(*left));
- if (! (lxdata.dflags & TRANSACTION_SORT_CALC)) {
- guarded_compute(sort_order, lxdata.sort_value, details_t(*left));
- lxdata.sort_value.reduce();
- lxdata.dflags |= TRANSACTION_SORT_CALC;
- }
-
- transaction_xdata_t& rxdata(transaction_xdata(*right));
- if (! (rxdata.dflags & TRANSACTION_SORT_CALC)) {
- guarded_compute(sort_order, rxdata.sort_value, details_t(*right));
- rxdata.sort_value.reduce();
- rxdata.dflags |= TRANSACTION_SORT_CALC;
- }
-
- DEBUG_PRINT("ledger.walk.compare_items_xact",
- "lxdata.sort_value = " << lxdata.sort_value);
- DEBUG_PRINT("ledger.walk.compare_items_xact",
- "rxdata.sort_value = " << rxdata.sort_value);
-
- return lxdata.sort_value < rxdata.sort_value;
-}
-
-transaction_xdata_t& transaction_xdata(const transaction_t& xact)
-{
- if (! xact.data)
- xact.data = new transaction_xdata_t();
- return *((transaction_xdata_t *) xact.data);
-}
-
-void add_transaction_to(const transaction_t& xact, value_t& value)
-{
- if (transaction_has_xdata(xact) &&
- transaction_xdata_(xact).dflags & TRANSACTION_COMPOUND) {
- value += transaction_xdata_(xact).value;
- }
- else if (xact.cost || ! value.realzero()) {
- value.add(xact.amount, xact.cost);
- }
- else {
- value = xact.amount;
- }
-}
-
-void truncate_entries::flush()
-{
- if (! xacts.size())
- return;
-
- entry_t * last_entry = (*xacts.begin())->entry;
-
- int l = 0;
- for (transactions_list::iterator x = xacts.begin();
- x != xacts.end();
- x++)
- if (last_entry != (*x)->entry) {
- l++;
- last_entry = (*x)->entry;
- }
- l++;
-
- last_entry = (*xacts.begin())->entry;
-
- int i = 0;
- for (transactions_list::iterator x = xacts.begin();
- x != xacts.end();
- x++) {
- if (last_entry != (*x)->entry) {
- last_entry = (*x)->entry;
- i++;
- }
-
- bool print = false;
- if (head_count) {
- if (head_count > 0 && i < head_count)
- print = true;
- else if (head_count < 0 && i >= - head_count)
- print = true;
- }
-
- if (! print && tail_count) {
- if (tail_count > 0 && l - i <= tail_count)
- print = true;
- else if (tail_count < 0 && l - i > - tail_count)
- print = true;
- }
-
- if (print)
- item_handler<transaction_t>::operator()(**x);
- }
- xacts.clear();
-
- item_handler<transaction_t>::flush();
-}
-
-void set_account_value::operator()(transaction_t& xact)
-{
- account_t * acct = xact_account(xact);
- assert(acct);
-
- account_xdata_t& xdata = account_xdata(*acct);
- add_transaction_to(xact, xdata.value);
-
- xdata.count++;
- if (xact.flags & TRANSACTION_VIRTUAL)
- xdata.virtuals++;
-
- item_handler<transaction_t>::operator()(xact);
-}
-
-void sort_transactions::post_accumulated_xacts()
-{
- std::stable_sort(transactions.begin(), transactions.end(),
- compare_items<transaction_t>(sort_order));
-
- for (transactions_deque::iterator i = transactions.begin();
- i != transactions.end();
- i++) {
- transaction_xdata(**i).dflags &= ~TRANSACTION_SORT_CALC;
- item_handler<transaction_t>::operator()(**i);
- }
-
- transactions.clear();
-}
-
-void calc_transactions::operator()(transaction_t& xact)
-{
- try {
-
- transaction_xdata_t& xdata(transaction_xdata(xact));
-
- if (last_xact && transaction_has_xdata(*last_xact)) {
- xdata.total += transaction_xdata_(*last_xact).total;
- xdata.index = transaction_xdata_(*last_xact).index + 1;
- } else {
- xdata.index = 0;
- }
-
- if (! (xdata.dflags & TRANSACTION_NO_TOTAL))
- add_transaction_to(xact, xdata.total);
-
- item_handler<transaction_t>::operator()(xact);
-
- last_xact = &xact;
-
- }
- catch (error * err) {
- err->context.push_front
- (new xact_context(xact, "Calculating transaction at"));
- throw err;
- }
-}
-
-void invert_transactions::operator()(transaction_t& xact)
-{
- if (transaction_has_xdata(xact) &&
- transaction_xdata_(xact).dflags & TRANSACTION_COMPOUND) {
- transaction_xdata_(xact).value.negate();
- } else {
- xact.amount.negate();
- if (xact.cost)
- xact.cost->negate();
- }
-
- item_handler<transaction_t>::operator()(xact);
-}
-
-
-static inline
-void handle_value(const value_t& value,
- account_t * account,
- entry_t * entry,
- unsigned int flags,
- std::list<transaction_t>& temps,
- item_handler<transaction_t>& handler,
- const datetime_t& date = datetime_t(),
- transactions_list * component_xacts = NULL)
-{
- temps.push_back(transaction_t(account));
- transaction_t& xact(temps.back());
- xact.entry = entry;
- xact.flags |= TRANSACTION_BULK_ALLOC;
- entry->add_transaction(&xact);
-
- // If there are component transactions to associate with this
- // temporary, do so now.
-
- if (component_xacts)
- transaction_xdata(xact).copy_component_xacts(*component_xacts);
-
- // If the account for this transaction is all virtual, then report
- // the transaction as such. This allows subtotal reports to show
- // "(Account)" for accounts that contain only virtual transactions.
-
- if (account && account_has_xdata(*account))
- if (! (account_xdata_(*account).dflags & ACCOUNT_HAS_NON_VIRTUALS)) {
- xact.flags |= TRANSACTION_VIRTUAL;
- if (! (account_xdata_(*account).dflags & ACCOUNT_HAS_UNB_VIRTUALS))
- xact.flags |= TRANSACTION_BALANCE;
- }
-
- transaction_xdata_t& xdata(transaction_xdata(xact));
-
- if (date)
- xdata.date = date;
-
- value_t temp(value);
-
- switch (value.type) {
- case value_t::BOOLEAN:
- case value_t::DATETIME:
- case value_t::INTEGER:
- temp.cast(value_t::AMOUNT);
- // fall through...
-
- case value_t::AMOUNT:
- xact.amount = *((amount_t *) temp.data);
- break;
-
- case value_t::BALANCE:
- case value_t::BALANCE_PAIR:
- xdata.value = temp;
- flags |= TRANSACTION_COMPOUND;
- break;
- }
-
- if (flags)
- xdata.dflags |= flags;
-
- handler(xact);
-}
-
-void collapse_transactions::report_subtotal()
-{
- assert(count >= 1);
-
- if (count == 1) {
- item_handler<transaction_t>::operator()(*last_xact);
- } else {
- entry_temps.push_back(entry_t());
- entry_t& entry = entry_temps.back();
- entry.payee = last_entry->payee;
- entry._date = last_entry->_date;
-
- handle_value(subtotal, &totals_account, last_entry, 0, xact_temps,
- *handler);
- }
-
- last_entry = NULL;
- last_xact = NULL;
- subtotal = 0L;
- count = 0;
-}
-
-void collapse_transactions::operator()(transaction_t& xact)
-{
- // If we've reached a new entry, report on the subtotal
- // accumulated thus far.
-
- if (last_entry && last_entry != xact.entry && count > 0)
- report_subtotal();
-
- add_transaction_to(xact, subtotal);
- count++;
-
- last_entry = xact.entry;
- last_xact = &xact;
-}
-
-void related_transactions::flush()
-{
- if (transactions.size() > 0) {
- for (transactions_list::iterator i = transactions.begin();
- i != transactions.end();
- i++) {
- if ((*i)->entry) {
- for (transactions_list::iterator j = (*i)->entry->transactions.begin();
- j != (*i)->entry->transactions.end();
- j++) {
- transaction_xdata_t& xdata = transaction_xdata(**j);
- if (! (xdata.dflags & TRANSACTION_HANDLED) &&
- (! (xdata.dflags & TRANSACTION_RECEIVED) ?
- ! ((*j)->flags & (TRANSACTION_AUTO | TRANSACTION_VIRTUAL)) :
- also_matching)) {
- xdata.dflags |= TRANSACTION_HANDLED;
- item_handler<transaction_t>::operator()(**j);
- }
- }
- } else {
- // This code should only be reachable from the "output"
- // command, since that is the only command which attempts to
- // output auto or period entries.
- transaction_xdata_t& xdata = transaction_xdata(**i);
- if (! (xdata.dflags & TRANSACTION_HANDLED) &&
- ! ((*i)->flags & TRANSACTION_AUTO)) {
- xdata.dflags |= TRANSACTION_HANDLED;
- item_handler<transaction_t>::operator()(**i);
- }
- }
- }
- }
-
- item_handler<transaction_t>::flush();
-}
-
-void changed_value_transactions::output_diff(const datetime_t& current)
-{
- value_t cur_bal;
-
- transaction_xdata(*last_xact).date = current;
- compute_total(cur_bal, details_t(*last_xact));
- cur_bal.round();
- transaction_xdata(*last_xact).date = 0;
-
- if (value_t diff = cur_bal - last_balance) {
- entry_temps.push_back(entry_t());
- entry_t& entry = entry_temps.back();
- entry.payee = "Commodities revalued";
- entry._date = current;
-
- handle_value(diff, NULL, &entry, TRANSACTION_NO_TOTAL, xact_temps,
- *handler);
- }
-}
-
-void changed_value_transactions::operator()(transaction_t& xact)
-{
- if (last_xact) {
- datetime_t moment;
- if (transaction_has_xdata(*last_xact))
- moment = transaction_xdata_(*last_xact).date;
- else
- moment = xact.date();
- output_diff(moment);
- }
-
- if (changed_values_only)
- transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED;
-
- item_handler<transaction_t>::operator()(xact);
-
- compute_total(last_balance, details_t(xact));
- last_balance.round();
-
- last_xact = &xact;
-}
-
-void component_transactions::operator()(transaction_t& xact)
-{
- if (handler && pred(xact)) {
- if (transaction_has_xdata(xact) &&
- transaction_xdata_(xact).have_component_xacts())
- transaction_xdata_(xact).walk_component_xacts(*handler);
- else
- (*handler)(xact);
- }
-}
-
-void subtotal_transactions::report_subtotal(const char * spec_fmt)
-{
- std::ostringstream out_date;
- if (! spec_fmt) {
- std::string fmt = "- ";
- fmt += date_t::output_format;
- finish.write(out_date, fmt);
- } else {
- finish.write(out_date, spec_fmt);
- }
-
- entry_temps.push_back(entry_t());
- entry_t& entry = entry_temps.back();
- entry.payee = out_date.str();
- entry._date = start;
-
- for (values_map::iterator i = values.begin();
- i != values.end();
- i++)
- handle_value((*i).second.value, (*i).second.account, &entry, 0,
- xact_temps, *handler, finish, &(*i).second.components);
-
- values.clear();
-}
-
-void subtotal_transactions::operator()(transaction_t& xact)
-{
- if (! start || xact.date() < start)
- start = xact.date();
- if (! finish || xact.date() > finish)
- finish = xact.date();
-
- account_t * acct = xact_account(xact);
- assert(acct);
-
- values_map::iterator i = values.find(acct->fullname());
- if (i == values.end()) {
- value_t temp;
- add_transaction_to(xact, temp);
- std::pair<values_map::iterator, bool> result
- = values.insert(values_pair(acct->fullname(),
- acct_value_t(acct, temp)));
- assert(result.second);
-
- if (remember_components)
- (*result.first).second.components.push_back(&xact);
- } else {
- add_transaction_to(xact, (*i).second.value);
-
- if (remember_components)
- (*i).second.components.push_back(&xact);
- }
-
- // If the account for this transaction is all virtual, mark it as
- // such, so that `handle_value' can show "(Account)" for accounts
- // that contain only virtual transactions.
-
- if (! (xact.flags & TRANSACTION_VIRTUAL))
- account_xdata(*xact_account(xact)).dflags |= ACCOUNT_HAS_NON_VIRTUALS;
- else if (! (xact.flags & TRANSACTION_BALANCE))
- account_xdata(*xact_account(xact)).dflags |= ACCOUNT_HAS_UNB_VIRTUALS;
-}
-
-void interval_transactions::report_subtotal(const datetime_t& moment)
-{
- assert(last_xact);
-
- start = interval.begin;
- if (moment)
- finish = moment - 86400L;
- else
- finish = last_xact->date();
-
- subtotal_transactions::report_subtotal();
-
- last_xact = NULL;
-}
-
-void interval_transactions::operator()(transaction_t& xact)
-{
- const datetime_t date = xact.date();
-
- if ((interval.begin && date < interval.begin) ||
- (interval.end && date >= interval.end))
- return;
-
- if (interval) {
- if (! started) {
- if (! interval.begin)
- interval.start(date);
- start = interval.begin;
- started = true;
- }
-
- datetime_t quant = interval.increment(interval.begin);
- if (date >= quant) {
- if (last_xact)
- report_subtotal(quant);
-
- datetime_t temp;
- while (date >= (temp = interval.increment(quant))) {
- if (quant == temp)
- break;
- quant = temp;
- }
- start = interval.begin = quant;
- }
-
- subtotal_transactions::operator()(xact);
- } else {
- item_handler<transaction_t>::operator()(xact);
- }
-
- last_xact = &xact;
-}
-
-by_payee_transactions::~by_payee_transactions()
-{
- for (payee_subtotals_map::iterator i = payee_subtotals.begin();
- i != payee_subtotals.end();
- i++)
- delete (*i).second;
-}
-
-void by_payee_transactions::flush()
-{
- for (payee_subtotals_map::iterator i = payee_subtotals.begin();
- i != payee_subtotals.end();
- i++)
- (*i).second->report_subtotal((*i).first.c_str());
-
- item_handler<transaction_t>::flush();
-
- payee_subtotals.clear();
-}
-
-void by_payee_transactions::operator()(transaction_t& xact)
-{
- payee_subtotals_map::iterator i = payee_subtotals.find(xact.entry->payee);
- if (i == payee_subtotals.end()) {
- payee_subtotals_pair
- temp(xact.entry->payee,
- new subtotal_transactions(handler, remember_components));
- std::pair<payee_subtotals_map::iterator, bool> result
- = payee_subtotals.insert(temp);
-
- assert(result.second);
- if (! result.second)
- return;
- i = result.first;
- }
-
- if (xact.date() > (*i).second->start)
- (*i).second->start = xact.date();
-
- (*(*i).second)(xact);
-}
-
-void set_comm_as_payee::operator()(transaction_t& xact)
-{
- entry_temps.push_back(*xact.entry);
- entry_t& entry = entry_temps.back();
- entry._date = xact.date();
- entry.code = xact.entry->code;
-
- if (xact.amount.commodity())
- entry.payee = xact.amount.commodity().symbol();
- else
- entry.payee = "<none>";
-
- xact_temps.push_back(xact);
- transaction_t& temp = xact_temps.back();
- temp.entry = &entry;
- temp.state = xact.state;
- temp.flags |= TRANSACTION_BULK_ALLOC;
-
- entry.add_transaction(&temp);
-
- item_handler<transaction_t>::operator()(temp);
-}
-
-void set_code_as_payee::operator()(transaction_t& xact)
-{
- entry_temps.push_back(*xact.entry);
- entry_t& entry = entry_temps.back();
- entry._date = xact.date();
-
- if (! xact.entry->code.empty())
- entry.payee = xact.entry->code;
- else
- entry.payee = "<none>";
-
- xact_temps.push_back(xact);
- transaction_t& temp = xact_temps.back();
- temp.entry = &entry;
- temp.state = xact.state;
- temp.flags |= TRANSACTION_BULK_ALLOC;
-
- entry.add_transaction(&temp);
-
- item_handler<transaction_t>::operator()(temp);
-}
-
-void dow_transactions::flush()
-{
- for (int i = 0; i < 7; i++) {
- start = finish = 0;
- for (transactions_list::iterator d = days_of_the_week[i].begin();
- d != days_of_the_week[i].end();
- d++)
- subtotal_transactions::operator()(**d);
- subtotal_transactions::report_subtotal("%As");
- days_of_the_week[i].clear();
- }
-
- subtotal_transactions::flush();
-}
-
-void generate_transactions::add_period_entries
- (period_entries_list& period_entries)
-{
- for (period_entries_list::iterator i = period_entries.begin();
- i != period_entries.end();
- i++)
- for (transactions_list::iterator j = (*i)->transactions.begin();
- j != (*i)->transactions.end();
- j++)
- add_transaction((*i)->period, **j);
-}
-
-void generate_transactions::add_transaction(const interval_t& period,
- transaction_t& xact)
-{
- pending_xacts.push_back(pending_xacts_pair(period, &xact));
-}
-
-void budget_transactions::report_budget_items(const datetime_t& moment)
-{
- if (pending_xacts.size() == 0)
- return;
-
- bool reported;
- do {
- reported = false;
- for (pending_xacts_list::iterator i = pending_xacts.begin();
- i != pending_xacts.end();
- i++) {
- datetime_t& begin = (*i).first.begin;
- if (! begin) {
- (*i).first.start(moment);
- begin = (*i).first.begin;
- }
-
- if (begin < moment &&
- (! (*i).first.end || begin < (*i).first.end)) {
- transaction_t& xact = *(*i).second;
-
- DEBUG_PRINT("ledger.walk.budget", "Reporting budget for "
- << xact_account(xact)->fullname());
- DEBUG_PRINT_TIME("ledger.walk.budget", begin);
- DEBUG_PRINT_TIME("ledger.walk.budget", moment);
-
- entry_temps.push_back(entry_t());
- entry_t& entry = entry_temps.back();
- entry.payee = "Budget entry";
- entry._date = begin;
-
- xact_temps.push_back(xact);
- transaction_t& temp = xact_temps.back();
- temp.entry = &entry;
- temp.flags |= TRANSACTION_AUTO | TRANSACTION_BULK_ALLOC;
- temp.amount.negate();
- entry.add_transaction(&temp);
-
- begin = (*i).first.increment(begin);
-
- item_handler<transaction_t>::operator()(temp);
-
- reported = true;
- }
- }
- } while (reported);
-}
-
-void budget_transactions::operator()(transaction_t& xact)
-{
- bool xact_in_budget = false;
-
- for (pending_xacts_list::iterator i = pending_xacts.begin();
- i != pending_xacts.end();
- i++)
- for (account_t * acct = xact_account(xact);
- acct;
- acct = acct->parent) {
- if (acct == xact_account(*(*i).second)) {
- xact_in_budget = true;
- // Report the transaction as if it had occurred in the parent
- // account.
- if (xact_account(xact) != acct)
- transaction_xdata(xact).account = acct;
- goto handle;
- }
- }
-
- handle:
- if (xact_in_budget && flags & BUDGET_BUDGETED) {
- report_budget_items(xact.date());
- item_handler<transaction_t>::operator()(xact);
- }
- else if (! xact_in_budget && flags & BUDGET_UNBUDGETED) {
- item_handler<transaction_t>::operator()(xact);
- }
-}
-
-void forecast_transactions::add_transaction(const interval_t& period,
- transaction_t& xact)
-{
- generate_transactions::add_transaction(period, xact);
-
- interval_t& i = pending_xacts.back().first;
- if (! i.begin) {
- i.start(datetime_t::now);
- i.begin = i.increment(i.begin);
- } else {
- while (i.begin < datetime_t::now)
- i.begin = i.increment(i.begin);
- }
-}
-
-void forecast_transactions::flush()
-{
- transactions_list passed;
- datetime_t last;
-
- while (pending_xacts.size() > 0) {
- pending_xacts_list::iterator least = pending_xacts.begin();
- for (pending_xacts_list::iterator i = ++pending_xacts.begin();
- i != pending_xacts.end();
- i++)
- if ((*i).first.begin < (*least).first.begin)
- least = i;
-
- datetime_t& begin = (*least).first.begin;
-
- if ((*least).first.end && begin >= (*least).first.end) {
- pending_xacts.erase(least);
- passed.remove((*least).second);
- continue;
- }
-
- transaction_t& xact = *(*least).second;
-
- entry_temps.push_back(entry_t());
- entry_t& entry = entry_temps.back();
- entry.payee = "Forecast entry";
- entry._date = begin;
-
- xact_temps.push_back(xact);
- transaction_t& temp = xact_temps.back();
- temp.entry = &entry;
- temp.flags |= TRANSACTION_AUTO;
- temp.flags |= TRANSACTION_BULK_ALLOC;
- entry.add_transaction(&temp);
-
- datetime_t next = (*least).first.increment(begin);
- if (next < begin || // wraparound
- (last && (next - last) > 365 * 5 * 24 * 3600))
- break;
- begin = next;
-
- item_handler<transaction_t>::operator()(temp);
-
- if (transaction_has_xdata(temp) &&
- transaction_xdata_(temp).dflags & TRANSACTION_MATCHES) {
- if (! pred(temp))
- break;
- last = temp.date();
- passed.clear();
- } else {
- bool found = false;
- for (transactions_list::iterator i = passed.begin();
- i != passed.end();
- i++)
- if (*i == &xact) {
- found = true;
- break;
- }
-
- if (! found) {
- passed.push_back(&xact);
- if (passed.size() >= pending_xacts.size())
- break;
- }
- }
- }
-
- item_handler<transaction_t>::flush();
-}
-
-template <>
-bool compare_items<account_t>::operator()(const account_t * left,
- const account_t * right)
-{
- assert(left);
- assert(right);
-
- account_xdata_t& lxdata(account_xdata(*left));
- if (! (lxdata.dflags & ACCOUNT_SORT_CALC)) {
- guarded_compute(sort_order, lxdata.sort_value, details_t(*left));
- lxdata.dflags |= ACCOUNT_SORT_CALC;
- }
-
- account_xdata_t& rxdata(account_xdata(*right));
- if (! (rxdata.dflags & ACCOUNT_SORT_CALC)) {
- guarded_compute(sort_order, rxdata.sort_value, details_t(*right));
- rxdata.dflags |= ACCOUNT_SORT_CALC;
- }
-
- return lxdata.sort_value < rxdata.sort_value;
-}
-
-account_xdata_t& account_xdata(const account_t& account)
-{
- if (! account.data)
- account.data = new account_xdata_t();
-
- return *((account_xdata_t *) account.data);
-}
-
-void sum_accounts(account_t& account)
-{
- account_xdata_t& xdata(account_xdata(account));
-
- for (accounts_map::iterator i = account.accounts.begin();
- i != account.accounts.end();
- i++) {
- sum_accounts(*(*i).second);
-
- xdata.total += account_xdata_(*(*i).second).total;
- xdata.total_count += (account_xdata_(*(*i).second).total_count +
- account_xdata_(*(*i).second).count);
- }
-
- value_t result;
- compute_amount(result, details_t(account));
- if (! result.realzero())
- xdata.total += result;
- xdata.total_count += xdata.count;
-}
-
-void sort_accounts(account_t& account,
- const value_expr_t * sort_order,
- accounts_deque& accounts)
-{
- for (accounts_map::iterator i = account.accounts.begin();
- i != account.accounts.end();
- i++)
- accounts.push_back((*i).second);
-
- std::stable_sort(accounts.begin(), accounts.end(),
- compare_items<account_t>(sort_order));
-}
-
-void walk_accounts(account_t& account,
- item_handler<account_t>& handler,
- const value_expr_t * sort_order)
-{
- handler(account);
-
- if (sort_order) {
- accounts_deque accounts;
- sort_accounts(account, sort_order, accounts);
- for (accounts_deque::const_iterator i = accounts.begin();
- i != accounts.end();
- i++) {
- account_xdata(**i).dflags &= ~ACCOUNT_SORT_CALC;
- walk_accounts(**i, handler, sort_order);
- }
- } else {
- for (accounts_map::const_iterator i = account.accounts.begin();
- i != account.accounts.end();
- i++)
- walk_accounts(*(*i).second, handler, NULL);
- }
-}
-
-void walk_accounts(account_t& account,
- item_handler<account_t>& handler,
- const std::string& sort_string)
-{
- if (! sort_string.empty()) {
- value_expr sort_order;
- sort_order.reset(parse_value_expr(sort_string));
- walk_accounts(account, handler, sort_order.get());
- } else {
- walk_accounts(account, handler);
- }
-}
-
-void walk_commodities(commodities_map& commodities,
- item_handler<transaction_t>& handler)
-{
- std::list<transaction_t> xact_temps;
- std::list<entry_t> entry_temps;
- std::list<account_t> acct_temps;
-
- for (commodities_map::iterator i = commodities.begin();
- i != commodities.end();
- i++) {
- if ((*i).second->flags() & COMMODITY_STYLE_NOMARKET)
- continue;
-
- entry_temps.push_back(entry_t());
- acct_temps.push_back(account_t(NULL, (*i).second->symbol()));
-
- if ((*i).second->history())
- for (history_map::iterator j = (*i).second->history()->prices.begin();
- j != (*i).second->history()->prices.end();
- j++) {
- entry_temps.back()._date = (*j).first;
-
- xact_temps.push_back(transaction_t(&acct_temps.back()));
- transaction_t& temp = xact_temps.back();
- temp.entry = &entry_temps.back();
- temp.amount = (*j).second;
- temp.flags |= TRANSACTION_BULK_ALLOC;
- entry_temps.back().add_transaction(&temp);
-
- handler(xact_temps.back());
- }
- }
-
- handler.flush();
-
- clear_entries_transactions(entry_temps);
-}
-
-} // namespace ledger
diff --git a/walk.h b/walk.h
deleted file mode 100644
index bd6bc2c2..00000000
--- a/walk.h
+++ /dev/null
@@ -1,751 +0,0 @@
-#ifndef _WALK_H
-#define _WALK_H
-
-#include "journal.h"
-#include "balance.h"
-#include "valexpr.h"
-#include "datetime.h"
-
-#include <iostream>
-#include <fstream>
-#include <deque>
-
-namespace ledger {
-
-template <typename T>
-struct item_handler {
- item_handler * handler;
-
- public:
- item_handler() : handler(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor item_handler<T>");
- }
- item_handler(item_handler * _handler) : handler(_handler) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor item_handler<T>");
- }
- virtual ~item_handler() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor item_handler<T>");
- }
-
- virtual void flush() {
- if (handler)
- handler->flush();
- }
- virtual void operator()(T& item) {
- if (handler)
- (*handler)(item);
- }
-};
-
-template <typename T>
-class compare_items {
- const value_expr_t * sort_order;
- public:
- compare_items(const value_expr_t * _sort_order)
- : sort_order(_sort_order) {
- assert(sort_order);
- }
- bool operator()(const T * left, const T * right);
-};
-
-template <typename T>
-bool compare_items<T>::operator()(const T * left, const T * right)
-{
- assert(left);
- assert(right);
-
- value_t left_result;
- value_t right_result;
- guarded_compute(sort_order, left_result, details_t(*left));
- guarded_compute(sort_order, right_result, details_t(*right));
-
- return left_result < right_result;
-}
-
-template <>
-bool compare_items<transaction_t>::operator()(const transaction_t * left,
- const transaction_t * right);
-template <>
-bool compare_items<account_t>::operator()(const account_t * left,
- const account_t * right);
-
-//////////////////////////////////////////////////////////////////////
-//
-// Transaction handlers
-//
-
-#define TRANSACTION_RECEIVED 0x0001
-#define TRANSACTION_HANDLED 0x0002
-#define TRANSACTION_TO_DISPLAY 0x0004
-#define TRANSACTION_DISPLAYED 0x0008
-#define TRANSACTION_NO_TOTAL 0x0010
-#define TRANSACTION_SORT_CALC 0x0020
-#define TRANSACTION_COMPOUND 0x0040
-#define TRANSACTION_MATCHES 0x0080
-
-struct transaction_xdata_t
-{
- value_t total;
- value_t sort_value;
- value_t value;
- unsigned int index;
- unsigned short dflags;
- datetime_t date;
- account_t * account;
- void * ptr;
-
- transactions_list * component_xacts;
-
- transaction_xdata_t()
- : index(0), dflags(0),
- account(NULL), ptr(NULL), component_xacts(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_xdata_t " << this);
- }
-
- ~transaction_xdata_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor transaction_xdata_t " << this);
- if (component_xacts)
- delete component_xacts;
- }
-
- void remember_xact(transaction_t& xact) {
- if (! component_xacts)
- component_xacts = new transactions_list;
- component_xacts->push_back(&xact);
- }
-
- bool have_component_xacts() const {
- return component_xacts != NULL && ! component_xacts->empty();
- }
-
- void copy_component_xacts(transactions_list& xacts) {
- for (transactions_list::const_iterator i = xacts.begin();
- i != xacts.end();
- i++)
- remember_xact(**i);
- }
-
- void walk_component_xacts(item_handler<transaction_t>& handler) const {
- for (transactions_list::const_iterator i = component_xacts->begin();
- i != component_xacts->end();
- i++)
- handler(**i);
- }
-};
-
-inline bool transaction_has_xdata(const transaction_t& xact) {
- return xact.data != NULL;
-}
-
-inline transaction_xdata_t& transaction_xdata_(const transaction_t& xact) {
- return *((transaction_xdata_t *) xact.data);
-}
-
-transaction_xdata_t& transaction_xdata(const transaction_t& xact);
-void add_transaction_to(const transaction_t& xact, value_t& value);
-
-inline account_t * xact_account(transaction_t& xact) {
- if (xact.data) {
- account_t * account = transaction_xdata(xact).account;
- if (account)
- return account;
- }
- return xact.account;
-}
-
-inline const account_t * xact_account(const transaction_t& xact) {
- return xact_account(const_cast<transaction_t&>(xact));
-}
-
-//////////////////////////////////////////////////////////////////////
-
-inline void walk_transactions(transactions_list::iterator begin,
- transactions_list::iterator end,
- item_handler<transaction_t>& handler) {
- for (transactions_list::iterator i = begin; i != end; i++)
- handler(**i);
-}
-
-inline void walk_transactions(transactions_list& list,
- item_handler<transaction_t>& handler) {
- walk_transactions(list.begin(), list.end(), handler);
-}
-
-inline void walk_entries(entries_list::iterator begin,
- entries_list::iterator end,
- item_handler<transaction_t>& handler) {
- for (entries_list::iterator i = begin; i != end; i++)
- walk_transactions((*i)->transactions, handler);
-}
-
-inline void walk_entries(entries_list& list,
- item_handler<transaction_t>& handler) {
- walk_entries(list.begin(), list.end(), handler);
-}
-
-//////////////////////////////////////////////////////////////////////
-
-class ignore_transactions : public item_handler<transaction_t>
-{
- public:
- virtual void operator()(transaction_t& xact) {}
-};
-
-class clear_transaction_xdata : public item_handler<transaction_t>
-{
- public:
- virtual void operator()(transaction_t& xact) {
- if (xact.data) {
- delete (transaction_xdata_t *) xact.data;
- xact.data = NULL;
- }
- }
-};
-
-class truncate_entries : public item_handler<transaction_t>
-{
- int head_count;
- int tail_count;
-
- transactions_list xacts;
-
- public:
- truncate_entries(item_handler<transaction_t> * handler,
- int _head_count, int _tail_count)
- : item_handler<transaction_t>(handler),
- head_count(_head_count), tail_count(_tail_count) {}
-
- virtual void flush();
- virtual void operator()(transaction_t& xact) {
- xacts.push_back(&xact);
- }
-};
-
-class set_account_value : public item_handler<transaction_t>
-{
- public:
- set_account_value(item_handler<transaction_t> * handler = NULL)
- : item_handler<transaction_t>(handler) {}
-
- virtual void operator()(transaction_t& xact);
-};
-
-class push_to_transactions_list : public item_handler<transaction_t>
-{
- public:
- transactions_list& xact_list;
-
- push_to_transactions_list(transactions_list& _xact_list)
- : xact_list(_xact_list) {}
-
- virtual void operator()(transaction_t& xact) {
- xact_list.push_back(&xact);
- }
-};
-
-class sort_transactions : public item_handler<transaction_t>
-{
- typedef std::deque<transaction_t *> transactions_deque;
-
- transactions_deque transactions;
- const value_expr_t * sort_order;
-
- public:
- sort_transactions(item_handler<transaction_t> * handler,
- const value_expr_t * _sort_order)
- : item_handler<transaction_t>(handler),
- sort_order(_sort_order->acquire()) {}
-
- sort_transactions(item_handler<transaction_t> * handler,
- const std::string& _sort_order)
- : item_handler<transaction_t>(handler) {
- assert(! _sort_order.empty());
- sort_order = parse_value_expr(_sort_order)->acquire();
- }
-
- virtual ~sort_transactions() {
- assert(sort_order);
- sort_order->release();
- }
-
- virtual void post_accumulated_xacts();
-
- virtual void flush() {
- post_accumulated_xacts();
- item_handler<transaction_t>::flush();
- }
-
- virtual void operator()(transaction_t& xact) {
- transactions.push_back(&xact);
- }
-};
-
-class sort_entries : public item_handler<transaction_t>
-{
- sort_transactions sorter;
- entry_t * last_entry;
-
- public:
- sort_entries(item_handler<transaction_t> * handler,
- const value_expr_t * _sort_order)
- : sorter(handler, _sort_order) {}
-
- sort_entries(item_handler<transaction_t> * handler,
- const std::string& _sort_order)
- : sorter(handler, _sort_order) {}
-
- virtual void flush() {
- sorter.flush();
- item_handler<transaction_t>::flush();
- }
-
- virtual void operator()(transaction_t& xact) {
- if (last_entry && xact.entry != last_entry)
- sorter.post_accumulated_xacts();
-
- sorter(xact);
-
- last_entry = xact.entry;
- }
-};
-
-class filter_transactions : public item_handler<transaction_t>
-{
- item_predicate<transaction_t> pred;
-
- public:
- filter_transactions(item_handler<transaction_t> * handler,
- const value_expr_t * predicate)
- : item_handler<transaction_t>(handler), pred(predicate) {}
-
- filter_transactions(item_handler<transaction_t> * handler,
- const std::string& predicate)
- : item_handler<transaction_t>(handler), pred(predicate) {}
-
- virtual void operator()(transaction_t& xact) {
- if (pred(xact)) {
- transaction_xdata(xact).dflags |= TRANSACTION_MATCHES;
- (*handler)(xact);
- }
- }
-};
-
-class calc_transactions : public item_handler<transaction_t>
-{
- transaction_t * last_xact;
-
- public:
- calc_transactions(item_handler<transaction_t> * handler)
- : item_handler<transaction_t>(handler), last_xact(NULL) {}
-
- virtual void operator()(transaction_t& xact);
-};
-
-class invert_transactions : public item_handler<transaction_t>
-{
- public:
- invert_transactions(item_handler<transaction_t> * handler)
- : item_handler<transaction_t>(handler) {}
-
- virtual void operator()(transaction_t& xact);
-};
-
-inline void clear_entries_transactions(std::list<entry_t>& entries_list) {
- for (std::list<entry_t>::iterator i = entries_list.begin();
- i != entries_list.end();
- i++)
- (*i).transactions.clear();
-}
-
-class collapse_transactions : public item_handler<transaction_t>
-{
- value_t subtotal;
- unsigned int count;
- entry_t * last_entry;
- transaction_t * last_xact;
- account_t totals_account;
-
- std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
-
- public:
- collapse_transactions(item_handler<transaction_t> * handler)
- : item_handler<transaction_t>(handler), count(0),
- last_entry(NULL), last_xact(NULL),
- totals_account(NULL, "<Total>") {}
-
- ~collapse_transactions() {
- clear_entries_transactions(entry_temps);
- }
-
- virtual void flush() {
- if (subtotal)
- report_subtotal();
- item_handler<transaction_t>::flush();
- }
-
- void report_subtotal();
-
- virtual void operator()(transaction_t& xact);
-};
-
-class component_transactions : public item_handler<transaction_t>
-{
- item_predicate<transaction_t> pred;
-
- public:
- component_transactions(item_handler<transaction_t> * handler,
- const value_expr_t * predicate)
- : item_handler<transaction_t>(handler), pred(predicate) {}
-
- component_transactions(item_handler<transaction_t> * handler,
- const std::string& predicate)
- : item_handler<transaction_t>(handler), pred(predicate) {}
-
- virtual void operator()(transaction_t& xact);
-};
-
-class related_transactions : public item_handler<transaction_t>
-{
- transactions_list transactions;
- bool also_matching;
-
- public:
- related_transactions(item_handler<transaction_t> * handler,
- const bool _also_matching = false)
- : item_handler<transaction_t>(handler),
- also_matching(_also_matching) {}
-
- virtual void flush();
- virtual void operator()(transaction_t& xact) {
- transaction_xdata(xact).dflags |= TRANSACTION_RECEIVED;
- transactions.push_back(&xact);
- }
-};
-
-class changed_value_transactions : public item_handler<transaction_t>
-{
- // This filter requires that calc_transactions be used at some point
- // later in the chain.
-
- bool changed_values_only;
- transaction_t * last_xact;
- value_t last_balance;
-
- std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
-
- public:
- changed_value_transactions(item_handler<transaction_t> * handler,
- bool _changed_values_only)
- : item_handler<transaction_t>(handler),
- changed_values_only(_changed_values_only), last_xact(NULL) {}
-
- ~changed_value_transactions() {
- clear_entries_transactions(entry_temps);
- }
-
- virtual void flush() {
- if (last_xact) {
- output_diff(datetime_t::now);
- last_xact = NULL;
- }
- item_handler<transaction_t>::flush();
- }
-
- void output_diff(const datetime_t& current);
-
- virtual void operator()(transaction_t& xact);
-};
-
-class subtotal_transactions : public item_handler<transaction_t>
-{
- struct acct_value_t {
- account_t * account;
- value_t value;
-
- transactions_list components;
-
- acct_value_t(account_t * a) : account(a) {}
- acct_value_t(account_t * a, value_t& v) : account(a), value(v) {}
- acct_value_t(const acct_value_t& av)
- : account(av.account), value(av.value) {}
- };
-
- typedef std::map<std::string, acct_value_t> values_map;
- typedef std::pair<std::string, acct_value_t> values_pair;
-
- protected:
- values_map values;
- bool remember_components;
-
- std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
-
- public:
- datetime_t start;
- datetime_t finish;
-
- subtotal_transactions(item_handler<transaction_t> * handler,
- bool _remember_components = false)
- : item_handler<transaction_t>(handler),
- remember_components(_remember_components) {}
-#ifdef DEBUG_ENABLED
- subtotal_transactions(const subtotal_transactions&) {
- assert(0);
- }
-#endif
- virtual ~subtotal_transactions() {
- clear_entries_transactions(entry_temps);
- }
-
- void report_subtotal(const char * spec_fmt = NULL);
-
- virtual void flush() {
- if (values.size() > 0)
- report_subtotal();
- item_handler<transaction_t>::flush();
- }
- virtual void operator()(transaction_t& xact);
-};
-
-class interval_expr_error : public error {
- public:
- interval_expr_error(const std::string& reason,
- error_context * ctxt = NULL) throw()
- : error(reason, ctxt) {}
- virtual ~interval_expr_error() throw() {}
-};
-
-class interval_transactions : public subtotal_transactions
-{
- interval_t interval;
- transaction_t * last_xact;
- bool started;
-
- public:
- interval_transactions(item_handler<transaction_t> * _handler,
- const interval_t& _interval,
- bool remember_components = false)
- : subtotal_transactions(_handler, remember_components),
- interval(_interval), last_xact(NULL), started(false) {}
-
- interval_transactions(item_handler<transaction_t> * _handler,
- const std::string& _interval,
- bool remember_components = false)
- : subtotal_transactions(_handler, remember_components),
- interval(_interval), last_xact(NULL), started(false) {}
-
- void report_subtotal(const datetime_t& moment = datetime_t());
-
- virtual void flush() {
- if (last_xact)
- report_subtotal();
- subtotal_transactions::flush();
- }
- virtual void operator()(transaction_t& xact);
-};
-
-class by_payee_transactions : public item_handler<transaction_t>
-{
- typedef std::map<std::string, subtotal_transactions *> payee_subtotals_map;
- typedef std::pair<std::string, subtotal_transactions *> payee_subtotals_pair;
-
- payee_subtotals_map payee_subtotals;
- bool remember_components;
-
- public:
- by_payee_transactions(item_handler<transaction_t> * handler,
- bool _remember_components = false)
- : item_handler<transaction_t>(handler),
- remember_components(_remember_components) {}
- virtual ~by_payee_transactions();
-
- virtual void flush();
- virtual void operator()(transaction_t& xact);
-};
-
-class set_comm_as_payee : public item_handler<transaction_t>
-{
- std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
-
- public:
- set_comm_as_payee(item_handler<transaction_t> * handler)
- : item_handler<transaction_t>(handler) {}
-
- ~set_comm_as_payee() {
- clear_entries_transactions(entry_temps);
- }
-
- virtual void operator()(transaction_t& xact);
-};
-
-class set_code_as_payee : public item_handler<transaction_t>
-{
- std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
-
- public:
- set_code_as_payee(item_handler<transaction_t> * handler)
- : item_handler<transaction_t>(handler) {}
-
- ~set_code_as_payee() {
- clear_entries_transactions(entry_temps);
- }
-
- virtual void operator()(transaction_t& xact);
-};
-
-class dow_transactions : public subtotal_transactions
-{
- transactions_list days_of_the_week[7];
-
- public:
- dow_transactions(item_handler<transaction_t> * handler,
- bool remember_components = false)
- : subtotal_transactions(handler, remember_components) {}
-
- virtual void flush();
- virtual void operator()(transaction_t& xact) {
- days_of_the_week[xact.date().wday()].push_back(&xact);
- }
-};
-
-class generate_transactions : public item_handler<transaction_t>
-{
- protected:
- typedef std::pair<interval_t, transaction_t *> pending_xacts_pair;
- typedef std::list<pending_xacts_pair> pending_xacts_list;
-
- pending_xacts_list pending_xacts;
- std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
-
- public:
- generate_transactions(item_handler<transaction_t> * handler)
- : item_handler<transaction_t>(handler) {}
-
- ~generate_transactions() {
- clear_entries_transactions(entry_temps);
- }
-
- void add_period_entries(period_entries_list& period_entries);
-
- virtual void add_transaction(const interval_t& period, transaction_t& xact);
-};
-
-#define BUDGET_NO_BUDGET 0x00
-#define BUDGET_BUDGETED 0x01
-#define BUDGET_UNBUDGETED 0x02
-
-class budget_transactions : public generate_transactions
-{
- unsigned short flags;
-
- public:
- budget_transactions(item_handler<transaction_t> * handler,
- unsigned long _flags = BUDGET_BUDGETED)
- : generate_transactions(handler), flags(_flags) {}
-
- void report_budget_items(const datetime_t& moment);
-
- virtual void operator()(transaction_t& xact);
-};
-
-class forecast_transactions : public generate_transactions
-{
- item_predicate<transaction_t> pred;
-
- public:
- forecast_transactions(item_handler<transaction_t> * handler,
- const value_expr_t * predicate)
- : generate_transactions(handler), pred(predicate) {}
-
- forecast_transactions(item_handler<transaction_t> * handler,
- const std::string& predicate)
- : generate_transactions(handler), pred(predicate) {}
-
- virtual void add_transaction(const interval_t& period,
- transaction_t& xact);
- virtual void flush();
-};
-
-
-//////////////////////////////////////////////////////////////////////
-//
-// Account walking functions
-//
-
-#define ACCOUNT_TO_DISPLAY 0x0001
-#define ACCOUNT_DISPLAYED 0x0002
-#define ACCOUNT_SORT_CALC 0x0004
-#define ACCOUNT_HAS_NON_VIRTUALS 0x0008
-#define ACCOUNT_HAS_UNB_VIRTUALS 0x0010
-
-struct account_xdata_t
-{
- value_t value;
- value_t total;
- value_t sort_value;
- unsigned int count; // transactions counted toward amount
- unsigned int total_count; // transactions counted toward total
- unsigned int virtuals;
- unsigned short dflags;
-
- account_xdata_t() : count(0), total_count(0), virtuals(0), dflags(0) {}
-};
-
-inline bool account_has_xdata(const account_t& account) {
- return account.data != NULL;
-}
-
-inline account_xdata_t& account_xdata_(const account_t& account) {
- return *((account_xdata_t *) account.data);
-}
-
-account_xdata_t& account_xdata(const account_t& account);
-
-//////////////////////////////////////////////////////////////////////
-
-class clear_account_xdata : public item_handler<account_t>
-{
- public:
- virtual void operator()(account_t& acct) {
- if (acct.data) {
- delete (account_xdata_t *) acct.data;
- acct.data = NULL;
- }
- }
-};
-
-void sum_accounts(account_t& account);
-
-typedef std::deque<account_t *> accounts_deque;
-
-void sort_accounts(account_t& account,
- const value_expr_t * sort_order,
- accounts_deque& accounts);
-void walk_accounts(account_t& account,
- item_handler<account_t>& handler,
- const value_expr_t * sort_order = NULL);
-void walk_accounts(account_t& account,
- item_handler<account_t>& handler,
- const std::string& sort_string);
-
-//////////////////////////////////////////////////////////////////////
-
-void walk_commodities(commodities_map& commodities,
- item_handler<transaction_t>& handler);
-
-inline void clear_journal_xdata(journal_t * journal) {
- clear_transaction_xdata xact_cleaner;
- walk_entries(journal->entries, xact_cleaner);
-
- clear_account_xdata acct_cleaner;
- walk_accounts(*journal->master, acct_cleaner);
-}
-
-} // namespace ledger
-
-#endif // _WALK_H
diff --git a/xml.cc b/xml.cc
deleted file mode 100644
index 418c6bf7..00000000
--- a/xml.cc
+++ /dev/null
@@ -1,476 +0,0 @@
-#include "xml.h"
-#include "journal.h"
-#include "datetime.h"
-#include "error.h"
-
-#include <iostream>
-#include <sstream>
-#include <cstring>
-
-extern "C" {
-#if defined(HAVE_EXPAT)
-#include <expat.h> // expat XML parser
-#elif defined(HAVE_XMLPARSE)
-#include <xmlparse.h> // expat XML parser
-#endif
-}
-
-namespace ledger {
-
-#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
-
-static XML_Parser current_parser;
-static unsigned int count;
-
-static journal_t * curr_journal;
-static entry_t * curr_entry;
-static commodity_t * curr_comm;
-static std::string comm_flags;
-
-static transaction_t::state_t curr_state;
-
-static std::string data;
-static bool ignore;
-static std::string have_error;
-
-static void startElement(void *userData, const char *name, const char **attrs)
-{
- if (ignore)
- return;
-
- if (std::strcmp(name, "entry") == 0) {
- assert(! curr_entry);
- curr_entry = new entry_t;
- curr_state = transaction_t::UNCLEARED;
- }
- else if (std::strcmp(name, "transaction") == 0) {
- assert(curr_entry);
- curr_entry->add_transaction(new transaction_t);
- if (curr_state != transaction_t::UNCLEARED)
- curr_entry->transactions.back()->state = curr_state;
- }
- else if (std::strcmp(name, "commodity") == 0) {
- if (std::string(attrs[0]) == "flags")
- comm_flags = attrs[1];
- }
- else if (std::strcmp(name, "total") == 0) {
- ignore = true;
- }
-}
-
-static void endElement(void *userData, const char *name)
-{
- if (ignore) {
- if (std::strcmp(name, "total") == 0)
- ignore = false;
- return;
- }
-
- if (std::strcmp(name, "entry") == 0) {
- assert(curr_entry);
- if (curr_journal->add_entry(curr_entry)) {
- count++;
- } else {
- account_t * acct = curr_journal->find_account("<Unknown>");
- curr_entry->add_transaction(new transaction_t(acct));
- if (curr_journal->add_entry(curr_entry)) {
- count++;
- } else {
- delete curr_entry;
- have_error = "Entry cannot be balanced";
- }
- }
- curr_entry = NULL;
- }
- else if (std::strcmp(name, "en:date") == 0) {
- curr_entry->_date = data;
- }
- else if (std::strcmp(name, "en:date_eff") == 0) {
- curr_entry->_date_eff = data;
- }
- else if (std::strcmp(name, "en:code") == 0) {
- curr_entry->code = data;
- }
- else if (std::strcmp(name, "en:cleared") == 0) {
- curr_state = transaction_t::CLEARED;
- }
- else if (std::strcmp(name, "en:pending") == 0) {
- curr_state = transaction_t::PENDING;
- }
- else if (std::strcmp(name, "en:payee") == 0) {
- curr_entry->payee = data;
- }
- else if (std::strcmp(name, "tr:account") == 0) {
- curr_entry->transactions.back()->account = curr_journal->find_account(data);
- }
- else if (std::strcmp(name, "tr:cleared") == 0) {
- curr_entry->transactions.back()->state = transaction_t::CLEARED;
- }
- else if (std::strcmp(name, "tr:pending") == 0) {
- curr_entry->transactions.back()->state = transaction_t::PENDING;
- }
- else if (std::strcmp(name, "tr:virtual") == 0) {
- curr_entry->transactions.back()->flags |= TRANSACTION_VIRTUAL;
- }
- else if (std::strcmp(name, "tr:generated") == 0) {
- curr_entry->transactions.back()->flags |= TRANSACTION_AUTO;
- }
- else if (std::strcmp(name, "symbol") == 0) {
- assert(! curr_comm);
- curr_comm = commodity_t::find_or_create(data);
- assert(curr_comm);
- curr_comm->add_flags(COMMODITY_STYLE_SUFFIXED);
- if (! comm_flags.empty()) {
- for (std::string::size_type i = 0, l = comm_flags.length(); i < l; i++) {
- switch (comm_flags[i]) {
- case 'P': curr_comm->drop_flags(COMMODITY_STYLE_SUFFIXED); break;
- case 'S': curr_comm->add_flags(COMMODITY_STYLE_SEPARATED); break;
- case 'T': curr_comm->add_flags(COMMODITY_STYLE_THOUSANDS); break;
- case 'E': curr_comm->add_flags(COMMODITY_STYLE_EUROPEAN); break;
- }
- }
- }
- }
-#if 0
- // jww (2006-03-02): !!!
- else if (std::strcmp(name, "price") == 0) {
- assert(curr_comm);
- amount_t * price = new amount_t(data);
- std::ostringstream symstr;
- symstr << curr_comm->symbol << " {" << *price << "}";
- commodity_t * priced_comm =
- commodity_t::find_commodity(symstr.str(), true);
- priced_comm->price = price;
- priced_comm->base = curr_comm;
- curr_comm = priced_comm;
- }
-#endif
- else if (std::strcmp(name, "quantity") == 0) {
- curr_entry->transactions.back()->amount.parse(data);
- if (curr_comm) {
- std::string::size_type i = data.find('.');
- if (i != std::string::npos) {
- int precision = data.length() - i - 1;
- if (precision > curr_comm->precision())
- curr_comm->set_precision(precision);
- }
- curr_entry->transactions.back()->amount.set_commodity(*curr_comm);
- curr_comm = NULL;
- }
- }
- else if (std::strcmp(name, "tr:amount") == 0) {
- curr_comm = NULL;
- }
-}
-
-static void dataHandler(void *userData, const char *s, int len)
-{
- if (! ignore)
- data = std::string(s, len);
-}
-
-bool xml_parser_t::test(std::istream& in) const
-{
- char buf[80];
-
- in.getline(buf, 79);
- if (std::strncmp(buf, "<?xml", 5) != 0) {
- in.clear();
- in.seekg(0, std::ios::beg);
- return false;
- }
-
- in.getline(buf, 79);
- if (! std::strstr(buf, "<ledger")) {
- in.clear();
- in.seekg(0, std::ios::beg);
- return false;
- }
-
- in.clear();
- in.seekg(0, std::ios::beg);
- return true;
-}
-
-unsigned int xml_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
-{
- char buf[BUFSIZ];
-
- count = 0;
- curr_journal = journal;
- curr_entry = NULL;
- curr_comm = NULL;
- ignore = false;
-
- unsigned int offset = 2;
- XML_Parser parser = XML_ParserCreate(NULL);
- current_parser = parser;
-
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, dataHandler);
-
- while (! in.eof()) {
- in.getline(buf, BUFSIZ - 1);
- std::strcat(buf, "\n");
- bool result;
- try {
- result = XML_Parse(parser, buf, std::strlen(buf), in.eof());
- }
- catch (const std::exception& err) {
- unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
- XML_ParserFree(parser);
- throw new parse_error(err.what());
- }
-
- if (! have_error.empty()) {
- unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
- parse_error err(have_error);
- std::cerr << "Error: " << err.what() << std::endl;
- have_error = "";
- }
-
- if (! result) {
- unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
- const char * err = XML_ErrorString(XML_GetErrorCode(parser));
- XML_ParserFree(parser);
- throw new parse_error(err);
- }
- }
-
- XML_ParserFree(parser);
-
- return count;
-}
-
-#endif // defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
-
-void xml_write_amount(std::ostream& out, const amount_t& amount,
- const int depth = 0)
-{
- for (int i = 0; i < depth; i++) out << ' ';
- out << "<amount>\n";
-
- commodity_t& c = amount.commodity();
- for (int i = 0; i < depth + 2; i++) out << ' ';
- out << "<commodity flags=\"";
- if (! (c.flags() & COMMODITY_STYLE_SUFFIXED)) out << 'P';
- if (c.flags() & COMMODITY_STYLE_SEPARATED) out << 'S';
- if (c.flags() & COMMODITY_STYLE_THOUSANDS) out << 'T';
- if (c.flags() & COMMODITY_STYLE_EUROPEAN) out << 'E';
- out << "\">\n";
- for (int i = 0; i < depth + 4; i++) out << ' ';
-#if 0
- // jww (2006-03-02): !!!
- if (c.price) {
- out << "<symbol>" << c.base->symbol << "</symbol>\n";
- for (int i = 0; i < depth + 4; i++) out << ' ';
- out << "<price>\n";
- xml_write_amount(out, *c.price, depth + 6);
- for (int i = 0; i < depth + 4; i++) out << ' ';
- out << "</price>\n";
- } else {
- out << "<symbol>" << c.symbol << "</symbol>\n";
- }
-#endif
- for (int i = 0; i < depth + 2; i++) out << ' ';
- out << "</commodity>\n";
-
- for (int i = 0; i < depth + 2; i++) out << ' ';
- out << "<quantity>";
- out << amount.quantity_string() << "</quantity>\n";
-
- for (int i = 0; i < depth; i++) out << ' ';
- out << "</amount>\n";
-}
-
-void xml_write_value(std::ostream& out, const value_t& value,
- const int depth = 0)
-{
- balance_t * bal = NULL;
-
- for (int i = 0; i < depth; i++) out << ' ';
- out << "<value type=\"";
- switch (value.type) {
- case value_t::BOOLEAN: out << "boolean"; break;
- case value_t::INTEGER: out << "integer"; break;
- case value_t::AMOUNT: out << "amount"; break;
- case value_t::BALANCE:
- case value_t::BALANCE_PAIR: out << "balance"; break;
- }
- out << "\">\n";
-
- switch (value.type) {
- case value_t::BOOLEAN:
- for (int i = 0; i < depth + 2; i++) out << ' ';
- out << "<boolean>" << *((bool *) value.data) << "</boolean>\n";
- break;
-
- case value_t::INTEGER:
- for (int i = 0; i < depth + 2; i++) out << ' ';
- out << "<integer>" << *((long *) value.data) << "</integer>\n";
- break;
-
- case value_t::AMOUNT:
- xml_write_amount(out, *((amount_t *) value.data), depth + 2);
- break;
-
- case value_t::BALANCE:
- bal = (balance_t *) value.data;
- // fall through...
-
- case value_t::BALANCE_PAIR:
- if (! bal)
- bal = &((balance_pair_t *) value.data)->quantity;
-
- for (int i = 0; i < depth + 2; i++) out << ' ';
- out << "<balance>\n";
-
- for (amounts_map::const_iterator i = bal->amounts.begin();
- i != bal->amounts.end();
- i++)
- xml_write_amount(out, (*i).second, depth + 4);
-
- for (int i = 0; i < depth + 2; i++) out << ' ';
- out << "</balance>\n";
- break;
-
- default:
- assert(0);
- break;
- }
-
- for (int i = 0; i < depth; i++) out << ' ';
- out << "</value>\n";
-}
-
-void output_xml_string(std::ostream& out, const std::string& str)
-{
- for (const char * s = str.c_str(); *s; s++) {
- switch (*s) {
- case '<':
- out << "&lt;";
- break;
- case '>':
- out << "&rt;";
- break;
- case '&':
- out << "&amp;";
- break;
- default:
- out << *s;
- break;
- }
- }
-}
-
-void format_xml_entries::format_last_entry()
-{
- output_stream << " <entry>\n"
- << " <en:date>" << last_entry->_date.to_string("%Y/%m/%d")
- << "</en:date>\n";
-
- if (last_entry->_date_eff)
- output_stream << " <en:date_eff>"
- << last_entry->_date_eff.to_string("%Y/%m/%d")
- << "</en:date_eff>\n";
-
- if (! last_entry->code.empty()) {
- output_stream << " <en:code>";
- output_xml_string(output_stream, last_entry->code);
- output_stream << "</en:code>\n";
- }
-
- if (! last_entry->payee.empty()) {
- output_stream << " <en:payee>";
- output_xml_string(output_stream, last_entry->payee);
- output_stream << "</en:payee>\n";
- }
-
- bool first = true;
- for (transactions_list::const_iterator i = last_entry->transactions.begin();
- i != last_entry->transactions.end();
- i++) {
- if (transaction_has_xdata(**i) &&
- transaction_xdata_(**i).dflags & TRANSACTION_TO_DISPLAY) {
- if (first) {
- output_stream << " <en:transactions>\n";
- first = false;
- }
-
- output_stream << " <transaction>\n";
-
- if ((*i)->_date)
- output_stream << " <tr:date>"
- << (*i)->_date.to_string("%Y/%m/%d")
- << "</tr:date>\n";
-
- if ((*i)->_date_eff)
- output_stream << " <tr:date_eff>"
- << (*i)->_date_eff.to_string("%Y/%m/%d")
- << "</tr:date_eff>\n";
-
- if ((*i)->state == transaction_t::CLEARED)
- output_stream << " <tr:cleared/>\n";
- else if ((*i)->state == transaction_t::PENDING)
- output_stream << " <tr:pending/>\n";
-
- if ((*i)->flags & TRANSACTION_VIRTUAL)
- output_stream << " <tr:virtual/>\n";
- if ((*i)->flags & TRANSACTION_AUTO)
- output_stream << " <tr:generated/>\n";
-
- if ((*i)->account) {
- std::string name = (*i)->account->fullname();
- if (name == "<Total>")
- name = "[TOTAL]";
- else if (name == "<Unknown>")
- name = "[UNKNOWN]";
-
- output_stream << " <tr:account>";
- output_xml_string(output_stream, name);
- output_stream << "</tr:account>\n";
- }
-
- output_stream << " <tr:amount>\n";
- if (transaction_xdata_(**i).dflags & TRANSACTION_COMPOUND)
- xml_write_value(output_stream,
- transaction_xdata_(**i).value, 10);
- else
- xml_write_value(output_stream, value_t((*i)->amount), 10);
- output_stream << " </tr:amount>\n";
-
- if ((*i)->cost) {
- output_stream << " <tr:cost>\n";
- xml_write_value(output_stream, value_t(*(*i)->cost), 10);
- output_stream << " </tr:cost>\n";
- }
-
- if (! (*i)->note.empty()) {
- output_stream << " <tr:note>";
- output_xml_string(output_stream, (*i)->note);
- output_stream << "</tr:note>\n";
- }
-
- if (show_totals) {
- output_stream << " <total>\n";
- xml_write_value(output_stream, transaction_xdata_(**i).total, 10);
- output_stream << " </total>\n";
- }
-
- output_stream << " </transaction>\n";
-
- transaction_xdata_(**i).dflags |= TRANSACTION_DISPLAYED;
- }
- }
-
- if (! first)
- output_stream << " </en:transactions>\n";
-
- output_stream << " </entry>\n";
-}
-
-} // namespace ledger
diff --git a/xml.h b/xml.h
deleted file mode 100644
index 216d48a3..00000000
--- a/xml.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef _XML_H
-#define _XML_H
-
-#include "parser.h"
-#include "format.h"
-
-namespace ledger {
-
-#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
-
-class xml_parser_t : public parser_t
-{
- public:
- virtual bool test(std::istream& in) const;
-
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
-};
-
-#endif
-
-class format_xml_entries : public format_entries
-{
- bool show_totals;
- public:
- format_xml_entries(std::ostream& output_stream,
- const bool _show_totals = false)
- : format_entries(output_stream, ""), show_totals(_show_totals) {
- output_stream << "<?xml version=\"1.0\"?>\n"
- << "<ledger version=\"2.6\" \
-xmlns:en=\"http://newartisans.com/xml/ledger-en\" \
-xmlns:tr=\"http://newartisans.com/xml/ledger-tr\">\n";
- }
-
- virtual void flush() {
- format_entries::flush();
- output_stream << "</ledger>" << std::endl;
- }
-
- virtual void format_last_entry();
-};
-
-} // namespace ledger
-
-#endif // _XML_H